4

我正在尝试使用 PDO 将“NULL”动态插入数据库。

表结构:

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查询:

$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))
    );      
}

例如,有时,值有时$fix['FixPM'][$i]是“NULL”。如何将其插入数据库?当我运行查询然后查看数据库中的数据时,这条记录显示 0.0000,而不是 null。

如何使用 PDO 插入 NULL 值?提供了一些解决方案。

  • 我认为我不能$stmt->execute(array( ':v1' => null, ':v2' => ... ))按照示例使用,因为有时该项目为空,有时则不是。因此,我需要引用我创建的变量,并在需要时$fix['FixPM'][$i]将其设为null

提前致谢。

4

1 回答 1

7

在我看来,这似乎是 PDO 准备好的语句仿真中的一个(n 未报告?)错误:

  1. 最终调用的实现;_PDOStatement::execute() pdo_parse_params()

  2. 反过来,尝试根据相关参数的数据类型引用/转义值(如参数所指示的那样$data_type-PDOStatement::bindValue()所有PDOStatement::bindParam()提供的参数$input_parametersPDOStatement::execute()被视为PDO::PARAM_STR,如该函数的文档中所述);

  3. 字符串类型的值通过调用相关数据库驱动程序的quoter()方法进行转义/引用,无论它们是否为null: 在 PDO_MySQL 的情况下,即mysql_handle_quoter(),它(最终)将值传递给mysqlnd_cset_escape_quotes()or mysql_cset_escape_slashes(),具体取决于服务器的NO_BACKSLASH_ESCAPESSQL 模式;

  4. 给定一个null参数,这两个函数都返回一个空字符串。

我的观点是,在打开参数的类型之前(在上面的步骤 2 中),pdo_parse_params()应该将类型设置为PDO::PARAM_NULLif 值为null. 但是,有些人可能会争辩说,这将null在适当的情况下阻止特定类型的值处理,在这种情况下,字符串大小写(在上面的步骤 3 中)肯定应该null在继续调用驱动程序方法之前处理值quoter()

作为临时解决方法,禁用准备好的语句仿真通常是最好的:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
于 2012-12-18T22:07:24.573 回答