PDOを使用してNULL値を挿入するにはどうすればよいですか?


105

私はこのコードを使用していて、私はフラストレーションを超えています:

try {
    $dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
    ...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem

PDO::PARAM_NULL, null, '', それらのすべてが失敗し、このエラーをスローします:

致命的なエラー:/ opt / ...で参照によりパラメーター2を渡すことができません

回答:


138

私はPDOを学んでいるが、私はあなたが使用する必要があると思うbindValue、ありませんbindParam

bindParam参照する変数を受け取り、の呼び出し時に値を取得しませんbindParam。私はこれをphpドキュメントのコメントで見つけました:

bindValue(':param', null, PDO::PARAM_INT);

編集:PSあなたはこれをやる気にさせるかもしれbindValue(':param', null, PDO::PARAM_NULL);ませんが、それは誰にとってもうまくいきませんでした(報告のためにウィルシェーバーに感謝します)。


両者の違いはわかりませんが、いくつか調べてみます。ありがとう、あなたの答えも素晴らしかったです。
ナチョ

3
これは私のものよりも良い答えだと思います(実際に機能する場合)
Joe Phillips

2
MySql 5.1.53でPDO :: PARAM_NULLに問題がありましたが、null値のPDO :: PARAM_INTはうまく機能しました。
シェーバーは

2
オーディン:最も重要な部分は、3つすべてのパラメーターを渡すことだと思います:)。ignの質問では、型としてではなくPDO :: PARAM_NULLを値として渡していました(型をまったく渡していないのです)
JasonWoof

1
参考までに:ほとんどの場合、を使用bindValue()しても問題はありませんbindParam()NULL価値のためだけでなく、すべてのために。パラメーターをPHP変数の参照にバインドする必要がある単一のケースは考えられませんが、それが実際に行われbindParam()ます。
low_rents

48

使用bindParam()するときは、定数ではなく変数を渡す必要があります。そのため、その行の前に変数を作成して、次のように設定する必要があります。null

$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);

試した場合も同じエラーメッセージが表示されます。

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);

あなたはそれを正しく理解しました、私は自分のコードで以前にそれを行ったことに気づきました、$ null = PDO :: PARAM_NULL; ありがとう。
ナチョ

1
とにかくプレースホルダーを作成する場合は、この場合はbindValue()を使用することをお勧めします。bindParam()はもともとクエリを実行することを目的としており、変数を変更して、パラメータを再度バインドせずに再実行します。bindValue()はすぐにバインドし、bindParam()は実行時にのみバインドします。
Hugo Zink、2015年

1
$ myNull = null行でnullは小文字でなければならないことがわかりました。$ myNull = NULLは機能しませんでした。
raphael75

27

INTEGER列を使用する場合(それはNULLMySQLで)、PDOには(私にとって)予期しない動作がいくつかあります。

を使用する場合$stmt->execute(Array)、リテラルを指定する必要NULLがありNULL、変数参照で指定することはできません。したがって、これは機能しません:

// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null

しかし、これはうまくいきます:

// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise

MySQL 5.5.15とPHP 5.4.1でこれを試しました


1
$ stmt-> execute(array( ':param' =>!empty($ val)?$ val:null)); 空の文字列の場合はデータベースにもnullを設定するため、!emptyを使用します
Shehzad Nizamani

1
@ShehzadNizamani列タイプが彼の例のように整数の場合のみ、はい。しかし、それ以外の場合isset()はによく相関しNULLます。空の文字列も値です。
StanE 2017年

8

問題がまだある(参照によってパラメーター2を渡すことができない)場合は、PDOにnullを渡すだけでなく、null値で変数を定義します。

bindValue(':param', $n = null, PDO::PARAM_INT);

お役に立てれば。


6

私は同じ問題を抱えていましたが、この解決策がbindParamで機能していることがわかりました:

    bindParam(':param', $myvar = NULL, PDO::PARAM_INT);

3

is またはのNULL場合にのみ挿入したいが、利用可能な場合はを挿入する場合。valueempty''value

A)POSTメソッドを使用してフォームデータを受信し、それらの値を使用して関数insertを呼び出します。

insert( $_POST['productId'], // Will be set to NULL if empty    
        $_POST['productName'] ); // Will be to NULL if empty                                

B)ユーザーがフィールドに入力しなかったかどうかを評価し、そうであれば挿入しNULLます。

public function insert( $productId, $productName )
{ 
    $sql = "INSERT INTO products (  productId, productName ) 
                VALUES ( :productId, :productName )";

    //IMPORTANT: Repace $db with your PDO instance
    $query = $db->prepare($sql); 

    //Works with INT, FLOAT, ETC.
    $query->bindValue(':productId',  !empty($productId)   ? $productId   : NULL, PDO::PARAM_INT); 

    //Works with strings.
    $query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR);   

    $query->execute();      
}

ユーザーが何も入力しない場合たとえば、productNameフォームのフィールドを、そして$productNameだろうSETけどEMPTY。したがって、それがであるかどうかを確認し、そうであるempty()場合はを挿入する必要がありますNULL

PHP 5.5.17でテスト済み

幸運を、


3
または、IFNULL()クエリ文字列でMySQLの関数を使用できます。このように:$sql = "INSERT INTO products ( productId, productName ), VALUES ( IFNULL(:productId, NULL), IFNULL(:productName, NULL) )";
starleaf1

私はあなたの解決策の清潔さが好きです。私はそれをテストしましたが、残念ながら、ユーザーが入力に何も入力しないと、NULLではなく空の文字列が挿入されます。それは好みの問題ですが、空の文字列ではなくNULLを持っています。
アリアンアコスタ2014

0

これを試して。

$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null

1
そのような古い質問に答えようとする前に、まず他の答えを読むべきです。すでに回答されている可能性があります。
常識2017年

0

他の回答に基づいていますが、このソリューションの実際の使用方法についてもう少し明確にしています。

たとえば、時間の値に空の文字列があり、それをnullとして保存する場合は、次のようにします。

  if($endtime == ""){
    $db->bind(":endtime",$endtime=NULL,PDO::PARAM_STR);
  }else{
    $db->bind("endtime",$endtime);
  }

時間は文字列として格納されるため、時間の値にはPARAM_STRを使用することに注意してください。


-1

私の場合、私は使用しています:

  • SQLite、

  • 不明な数のフィールドを処理するためのプレースホルダー付きの準備済みステートメント

  • AJAX要求は、ユーザによって送られたすべてが文字列であるなど、そのようなものは存在しないNULL値をと

  • 外部キーの制約(許容値)にNULL違反しないため、私は必死にs を挿入する必要があります。

今、ユーザーが空の文字列またはorの$_POST[field1]value1を使用してpost:で送信するとします。"""null""NULL"

最初に私は声明を出します:

$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");

どこ{$sColumns}のようなSTHであるfield1, field2, ...{$sValues}私のプレースホルダです?, ?, ...

その後、私は私の収集$_POST、アレイ内の列名と関連データを$values に置き換えNULLS:

  for($i = 0; $i < \count($values); $i++)
     if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
        $values[$i] = null;

今、私は実行することができます:

$stmt->execute($values);

そして、とりわけ、外部キー制約をバイパスします。

一方、空の文字列の方が意味がある場合は、そのフィールドが外部キーの一部であるかどうかを確認する必要があります(より複雑)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.