I am trying to dynamically insert 'NULL' into the database using PDO.
TABLE STRUCTURE:
CREATE TABLE IF NOT EXISTS `Fixes` (
`Id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'PK',
`CurrencyId` int(11) NOT NULL COMMENT 'FK',
`MetalId` int(11) NOT NULL COMMENT 'FK',
`FixAM` decimal(10,5) NOT NULL,
`FixPM` decimal(10,5) DEFAULT NULL,
`TimeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`Id`),
KEY `CurrencyId` (`CurrencyId`),
KEY `MetalId` (`MetalId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=13 ;
PHP / PDO QUERY:
$sql = 'UPDATE
Fixes
SET
FixAM = :fixAM,
FixPM = :fixPM
WHERE
MetalId IN (SELECT Id FROM Metals WHERE Name = :metal) AND
CurrencyId IN (SELECT Id FROM Currencies Where Id = :currency)';
$stmt = $db->prepare($sql);
for ($i = 0; $i<3; $i++) {
$stmt->execute(array(
':metal' => 'Silver',
':fixAM' => $fix['FixAM'][$i],
':fixPM' => $fix['FixPM'][$i],
':currency' => ($i+1))
);
}
e.g. sometimes, the value for $fix['FixPM'][$i]
is sometimes 'NULL'. How do I insert this into the database? When I run the query and then view the data in the database, this record shows 0.0000, and not null.
How do I insert NULL values using PDO? provides a few solutions.
- I dont think I can use
$stmt->execute(array( ':v1' => null, ':v2' => ... ))
as per example because sometimes the item is null, and sometimes not. As such, I need to refer to the variable I have created$fix['FixPM'][$i]
and make that null as and when needed
Thanks in advance.
This appears to me to be a(n unreported?) bug in PDO's prepared statement emulation:
the implementation of
PDOStatement::execute()
eventually invokespdo_parse_params()
;that, in turn, attempts to quote/escape values based on the relevant parameter's data type (as indicated by the
$data_type
arguments toPDOStatement::bindValue()
andPDOStatement::bindParam()
—all parameters provided as$input_parameters
toPDOStatement::execute()
are treated asPDO::PARAM_STR
, as stated in the documentation of that function);string-typed values are escaped/quoted by calling the relevant database driver's
quoter()
method irrespective of whether they arenull
: in the case of PDO_MySQL, that'smysql_handle_quoter()
, which (eventually) passes the value to eithermysqlnd_cset_escape_quotes()
ormysql_cset_escape_slashes()
, depending on the server'sNO_BACKSLASH_ESCAPES
SQL mode;given a
null
argument, both of those functions return an empty string.My opinion is that, prior to switching on the parameter's type (in step 2 above),
pdo_parse_params()
should set the type toPDO::PARAM_NULL
if the value isnull
. However, some might argue that this would prevent type-specific handling ofnull
values where appropriate, in which case the string case (in step 3 above) should definitely handlenull
values before proceeding with a call to the driver'squoter()
method.As an interim workaround, disabling prepared statement emulation is usually for the best anyway: