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' => ... ))アイテムがnullの場合もあれば、そうでない場合もあるため、例のように使用できるとは思いません。そのため、作成した変数を参照し、必要に応じてその変数を$fix['FixPM'][$i]nullする必要があります

前もって感謝します。

4

1 に答える 1

7

これは、PDO のプリペアド ステートメント エミュレーションの (報告されていない?) バグのように思えます。

  1. 最終的に呼び出すの実装PDOStatement::execute() pdo_parse_params()

  2. 次に、関連するパラメーターのデータ型に基づいて値を引用/エスケープしようとします$data_type(引数 toPDOStatement::bindValue()および — toPDOStatement::bindParam()として提供されるすべてのパラメーターは、その関数のドキュメントに記載されているように として扱われます)。$input_parametersPDOStatement::execute()PDO::PARAM_STR

  3. 文字列型の値は、それらが であるかどうかに関係なく、関連するデータベース ドライバーのメソッドを呼び出すことによってエスケープ/クォートされます。quoter()nullmysql_handle_quoter()mysqlnd_cset_escape_quotes()mysql_cset_escape_slashes()NO_BACKSLASH_ESCAPES

  4. 引数を指定するnullと、これらの関数はどちらも空の文字列を返します。

私の意見では、(上記のステップ 2 で)パラメータのタイプをオンにする前に、値が の場合、pdo_parse_params()タイプを に設定する必要があります。ただし、これにより、適切な場合に型固有の値の処理が妨げられると主張する人もいるかもしれません。その場合、ドライバーのメソッドの呼び出しに進む前に、文字列のケース(上記の手順 3) で値を確実に処理する必要があります。PDO::PARAM_NULLnullnullnullquoter()

暫定的な回避策として、準備済みステートメントのエミュレーションを無効にすることが通常は最善の方法です。

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