Using timestamp type with pg_prepare - php

Running the following code:
$preCallMatch = pg_prepare($dbcp, 'callMatch',
"SELECT duration
FROM voip_calls
WHERE system_id = $1
AND call_start => $2
AND call_start <= $3
AND destination = $4");
I get the following error:
Warning: pg_prepare(): Query failed: ERROR: operator does not exist: timestamp without time zone => "unknown"
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. in /home/www/dinesh/UPSReconcileZeroSecondCalls.php on line 38
I have tried casting $2 in this manner with no luck:
$preCallMatch = pg_prepare($dbcp, 'callMatch',
"SELECT duration
FROM voip_calls
WHERE system_id = $1
AND call_start => CAST ( $2 AS TIMESTAMP )
AND call_start <= CAST ( $3 AS TIMESTAMP )
AND destination = $4");
Warning: pg_prepare(): Query failed: ERROR: operator does not exist: timestamp without time zone => timestamp without time zone
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts. in /home/www/dinesh/UPSReconcileZeroSecondCalls.php on line 38
Column types from voip_calls table:
call_start | timestamp without time zone |
call_end | timestamp without time zone | not null
Any tips as to what I'm doing wrong? Note, PDO or MDPD aren't an option right now.
Versions of software:
ii php5 5.2.6.dfsg.1-1+lenny3 server-side, HTML-embedded scripting languag
ii libapache2-mod-php5 5.2.6.dfsg.1-1+lenny3 server-side, HTML-embedded scripting languag
ii php5-pgsql 5.2.6.dfsg.1-1+lenny3 PostgreSQL module for php5
ii libpq5 8.3.8-0lenny1 PostgreSQL C client library
postmaster (PostgreSQL) 8.1.4

It may be your => operator causing the problem - try >= instead.
Also as a hint I find it easier to write $2::timestamp instead of CAST($2 AS TIMESTAMP) - it is a PostgreSQL-specific syntax but for me reads better (and it's less to type ;-) )

Turns out it was the <= and => operators. Doing this works fine:
$preCallMatch = pg_prepare($dbcp, 'callMatch',
"SELECT duration
FROM voip_calls
WHERE system_id = $1
AND call_start BETWEEN $2 AND $3
AND destination = $4");

Related

Sum Column with Oracle 11 and PHP - what's wrong?

Trying to get a simply query going through and its not working - newbie here.
Other php files and queries do run well.
$sql = "select sum(rese_nshw) as noshows from tnht_eseo where edta_data = '19.10.01'" ;
$sumParse = oci_parse($conn, $sql);
oci_define_by_name($sumParse, "noshows", $total);
oci_execute($sumParse);
while(oci_fetch($sumParse)){
echo "noshows:". $total;
}
what's wrong ? just outputs blank.
Running the SQL query in Oracle directly, it outputs 6 as NOSHOWS for this query.
If EDTA_DATA is date (datatype), don't compare it to a string as '19.10.01' is a string. Oracle will implicitly try to convert it to appropriate date, but that doesn't have to work always. Besides 19.10.01 can be anything (2019 Oct 01, or 19 Oct 2001, or ...), depends on NLS settings.
Take control over it; see whether using date literal helps (it always has yyyy-mm-dd format):
where edta_data = date '2019-10-01'
Furthermore, if edta_data contains time component (hours, minutes, seconds), then the simplest option is to truncate it, e.g.
where trunc(edta_data) = date '2019-10-01'
but it'll prevent Oracle from using index on that column (if it exists). It can be fixed, no problem; but - first see whether anything of above helps.
You have to use Upper Case as defined here:
column_name The column name used in the query.
Use uppercase for Oracle's default, non-case sensitive column names.
Use the exact column name case for case-sensitive column names.
from: https://www.php.net/manual/en/function.oci-define-by-name.php
Then:
oci_define_by_name($sumParse, "NOSHOWS", $total);

PDO Insert not accepting "true" or "false", but only 0 and 1

After introducing phinx as a database migration tool, I am no longer able to use true and false through PDO's execute statement. Whenever I do, I get the following error:
PHP Warning: PDOStatement::execute(): SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect integer value: '' for column 'my_db'.'my_table'.'my_column' at row 1...
My table has the following schema (shorted):
| Field | Type | Null | Key | Default | Extra |
+-------------------------------+--------------+------+-----+---------+----------------+
| my_column | tinyint(1) | NO | | NULL | |
+-------------------------------+--------------+------+-----+---------+----------------+
I am using the following code (shorted):
$stmt = $this->pdo->prepare("INSERT INTO `$table` (`my_column`) VALUES (:mycolumn)");
$stmt->execute([
'my_column' => false
]);
The column is created by the migration script with:
->addColumn('my_column', 'boolean', [
'null' => false,
'after' => 'another_column',
])
The strange thing is, that I have no problems with using true and false in manual sql statements through phpMyAdmin.
you can use PDO::PARAM_BOOL in PDO
$stmt->bindValue(':myColumn', false, PDO::PARAM_BOOL);
This happened to me when i use macOS,
i was building my website from Windows 10, and works fine.
After using macOS i had to change the variables to 1 or 0
I hope you fixed it.
A solution to that problem is to set sql_mode = '' globally.
Run this query in you DB and check if it fixes the issue:
set GLOBAL sql_mode = "";
You can read up on Server SQL Modes here
P.S. you have to run that query everytime you restart your mysql server. To overcome this you have to set it in mysql config which you can look it up if required.
Your field type is tinyint(1). so it supports only values from 0-9 . Change to to varchar, text, char etc to accept true/false string.
But i strongly suggest you to use bool datatype. Then use 0 or 1 as true or false. There is no point in writing string (true/false) values for boolean operations. Using 0 or 1 will save you from lot of troubles in the future.

Converting Date column to ODBC canonical format in SQL Server 2005

I'm dealing with the issue of converting a Date column to an ODBC canonical format in my Microsoft SQL Server 2008.
I have the following SQL query in php:
$sql_query = "UPDATE [$connectionInfo[Database]].[dbo].[log_record] SET [lock]='0' WHERE CONVERT [Date] = '".json_encode($value['Date']['date'])."'
Basically, the part '".json_encode($value['Date']['date'])."' works and is printed as '"2017-06-01 00:00:00"'. But it's the [Date] column that's the problem. How can I compare them? It generates the following error:
error: Conversion failed when converting date and/or time from
character string. query: UPDATE [dba_sql].[dbo].[log_record] SET
[lock]='0' WHERE [Date] = '"2017-06-01 00:00:00"'
I attempted the following, but in vain:
$sql_query = "UPDATE [$connectionInfo[Database]].[dbo].[log_record] SET [lock]='0' WHERE CONVERT CONVERT(varchar, Date, 120) = '".json_encode($value['Date']['date'])."'
Get rid of the double quotes, and remove the convert hanging in your code. There is no need to convert the date in your table to a character type for your comparison.
The following is valid: select convert(date,'2017-06-01 00:00:00')
This is not: select convert(date,'"2017-06-01 00:00:00"')
rextester demo: http://rextester.com/NUNAD13593
Also note: The only truly safe formats for date/time literals in SQL Server, at least for datetime and smalldatetime, are: YYYYMMDD and YYYY-MM-DDThh:mm:ss[.nnn]
Reference: Bad habits to kick : mis-handling date / range queries - Aaron Bertrand
For example, if you have a language setting that implicitly sets the dateformat to dmy, then the same input for two different conversions can yield different output, if not an error:
set language 'british';
select toDatatype = 'datetime' ,val = convert(char(10),convert(datetime,'2017-06-01 00:00:00'),120)
union all
select toDatatype = 'date', val = convert(char(10),convert(date,'2017-06-01 00:00:00'),120)
returns:
+------------+------------+
| toDatatype | val |
+------------+------------+
| datetime | 2017-01-06 |
| date | 2017-06-01 |
+------------+------------+
and select convert(datetime,'2017-06-13') would return an error where as select convert(date,'2017-06-13') would return 2017-06-13.

Error during insert with parameter(s) over 30 characters

Issue
Performing an insert using prepared statements with PDO and an ODBC driver gives the following error when at least one of the parameters is over 30 characters:
SQLSTATE[HY010]: Function sequence error: 0
[unixODBC][Driver Manager]Function sequence error (SQLExecute[0] at /usr/src/builddir/ext/pdo_odbc/odbc_stmt.c:254)
Inserts work for any bound string that is <= 30 characters in length.
I have no issues with SELECT queries.
Using INSERT with isql and sqlcmd does not produce an error, but the column values are truncated in the database if they are over 30 characters.
It appears to be a driver issue.
Any ideas on what is causing the issue, and how it can be solved?
Example
Below is a minimal example duplicating the error on my system in PHP, isql, and sqlcmd.
The table used (called table) has three columns:
colvarchar varchar(70)
colnvarchar nvarchar(40)
colnchar nchar(60)
And the code that produces the error:
<?php
$dns = 'odbc:testdb';
$username = 'user';
$password = 'pass';
$pdo = new PDO($dns, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = <<<'QUERY'
INSERT INTO table
(colvarchar, colnvarchar, colnchar)
VALUES
(CAST(:colvarchar AS varchar)
CAST(:colnvarchar AS nvarchar),
CAST(:colnchar AS nchar));
QUERY;
$prepStmt = $pdo->prepare($sql);
// Add one more characters to any of the following strings to cause the error
$prepStmt->bindValue('colvarchar', '012345678901234567890123456789');
$prepStmt->bindValue('colnvarchar', '012345678901234567890123456789');
$prepStmt->bindValue('colnchar', '012345678901234567890123456789');
$prepStmt->execute();
?>
Adding an additional characters to any of the 30 character strings will cause the following error:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY010]: Function sequence error: 0 [unixODBC][Driver Manager]Function sequence error (SQLExecute[0] at /usr/src/builddir/ext/pdo_odbc/odbc_stmt.c:254)' in ...
Using isql and sqlcmd from command line performs the insert, but a select on the table shows the strings are truncated to 30 characters.
slqcmd:
sqlcmd -D -S testdb -U user -P pass -q "INSERT INTO table (colvarchar,
colnvarchar, colnchar) VALUES
(CAST('012345678901234567890123456789xxx' AS varchar),
CAST('012345678901234567890123456789xxx' AS nvarchar),
CAST('012345678901234567890123456789xxx' AS nchar))"
(1 rows affected)
isql:
isql testdb -U user -P pass
SQL> INSERT INTO table (colvarchar,
colnvarchar, colnchar) VALUES
(CAST('012345678901234567890123456789xxx' AS varchar),
CAST('012345678901234567890123456789xxx' AS nvarchar),
CAST('012345678901234567890123456789xxx' AS nchar))"
SQLRowCount returns 1
Result:
SELECT colvarchar, colnvarchar, colnchar FROM table;
colvarchar | colnvarchar | colnchar
012345678901234567890123456789 | 012345678901234567890123456789 | 012345678901234567890123456789
012345678901234567890123456789 | 012345678901234567890123456789 | 012345678901234567890123456789
Research
This post details a similar issue with inserts that do not conform to max column width, timestamp format, or column type.
Timestamp format has been tested and does work, since it is less than 30 characters.
Test strings over 30 characters have been checked to make sure their length is less than the max width of their column.
The datatype of the problematic columns are varchar.
System Setup
OS: Debian wheezy (64bit)
Database: Microsoft SQL Server 2014
Webserver: Apache 2.2.22 (64bit)
PHP 5.6.24 with Zend thread safety (64bit)
Microsoft ODBC Driver 11.0.2270.0 (Red Hat Linux) (64bit)
created appropriate environment to work with Debian according to this blog and spiceworks
unixODBC 2.3.0 (64bit)
required by the MS ODBC driver on linux
UPDATE:
I believe this to be a unixODBC issue, as the 30 character truncation was present when I was using FreeTDS and unixODBC (which was changed to MS ODBC and unixODBC because of this issue). The difference was there was no error message when using FreeTDS; it failed silently like isql and sqlcmd are doing presently.
Changed unixODBC version to 2.3.0 from 2.3.4 for its compatibility with MS ODBC 11, as shown here. Issue persists.
All programs that required ODBC shared libraries were linking with versions that were from 2011. They now all link with the update to date shared libraries from unixODBC. Issue persists.
You CAST to NVARCHAR and NVARCHAR is limited to 30 characters in SQL-Server
make the cast like this:
CAST (colvarchar AS varchar(70) )
CAST (colnvarchar AS nvarchar(40) )
CAST (colnchar AS nchar(60) )
The issue is with the SQL CAST expressions.
From MSDN - CAST & CONVERT:
Truncating and Rounding Results
When you convert character or binary expressions (char, nchar,
nvarchar, varchar, binary, or varbinary) to an expression of a
different data type, data can be truncated, only partially displayed,
or an error is returned because the result is too short to display.
The documentation lists specific exceptions that are guaranteed not to be truncated. However, it does not detail what length data will be truncated too.
Specify the data type length to avoid the truncation:
CAST (colvarchar AS varchar(70))
CAST (colnvarchar AS nvarchar(40))
CAST (colnchar AS nchar(60))

MySQL select b'1' returns integer 1 or ASCII character 1 depending on environment

On my home computer,
mysql_fetch_row( mysql_query(" select b'1' ") )[0]
returns string "1".
But when hosted on webserver it returns string having ASCII character 1.
Doc does say-
Bit values are returned as binary values. To display them in printable
form, add 0 or use a conversion function such as BIN().
But on my local machine it still returns "1" without any conversion done by me.
How can I have the same behavior on my web server?
If I get the same behavior then I don't have to convert my PHP codes from like
$row = mysql_fetch_row( mysql_query(" select bit1_field from .. where .. ") );
if( $row[0] === '1' ) ...;
to
... select bit1_field+0 as bit1_field ...
where bit1_field is of type bit(1).
It seems you are using two different drivers on the machines. There are two, php5-mysqlnd and php5-mysql. Website Factor wrote about the different behavior for BIT field in late April and I have also several machines with same version, but different drives. I's probably because the driver is not changed when upgrading from an earlier version, but when php >5.4 is installed, it gets installed with php5-mysqlnd by default. Here is the MySQL page about the differences.

Categories