1

now() + INTERVALこのINSERT ステートメントを名前付きプレースホルダーを持つ PDO 準備済みステートメントに変換する際に問題が発生しています。

'now() + INTERVAL 3 DAY'またはを使用して値をバインドすると、正しい日時(0000-00-00 00:00:00)'DATE_ADD(now(), INTERVAL 3 DAY)'の代わりに 000 が挿入されます。

これは私が以前に使用していたものです:

$qry = "INSERT INTO password_reset(user_id, temp_password, expiry_date) 
VALUES('$member_user_id','$temp_password', now() + INTERVAL 3 DAY)";

新しい PDO ステートメント:

$stmt = $conn->prepare('INSERT INTO password_reset (user_id, temp_password, expiry_date) 
VALUES(:user_id, :temp_password, :expiry_date)');          
$stmt->bindValue(':user_id', $member_user_id); 
$stmt->bindValue(':temp_password', $random_password); 
$stmt->bindValue(':expiry_date', 'now() + INTERVAL 3 DAY');  
$insertResult = $stmt->execute();                

私もこれを試しました:

$stmt->bindValue(':expiry_date', 'DATE_ADD(now(), INTERVAL 3 DAY)'); 

いくつかのSO投稿で提案された代替方法

いくつかの SO 投稿(このリンクを含む)では、now() ステートメントをバインドする代わりに VALUES に配置することを提案しましたが、これによりエラー メッセージ「無効なパラメーター番号: バインドされた変数の数がトークンの数と一致しません」が発生します。

$stmt = $conn->prepare('INSERT INTO password_reset (user_id, temp_password, expiry_date) 
VALUES(:user_id, :temp_password, :now() + INTERVAL 3 DAY)');
$stmt->bindValue(':user_id', $member_user_id); 
$stmt->bindValue(':temp_password', $random_password); 
$insertResult = $stmt->execute(); 
4

2 に答える 2

2

目の前にコロンがあります:now()
それだけです。ただのタイプミス。

2番目のエラーメッセージは、コロンを実際に削除したのではなく、他の何か(おそらく引用符)を削除したことを明確に示しています。あなたは書くことにもっと注意を払う必要があります。そして、エラーメッセージにもっと注意を払ってください、それらは非常に有益です。

于 2013-01-29T16:49:39.143 に答える
2

からコロンを削除し:now() + INTERVAL 3 DAYます。

$stmt = $conn->prepare('INSERT INTO password_reset (user_id, temp_password, expiry_date) 
VALUES(:user_id, :temp_password, now() + INTERVAL 3 DAY)');
$stmt->bindValue(':user_id', $member_user_id); 
$stmt->bindValue(':temp_password', $random_password); 
$insertResult = $stmt->execute(); 

または、次のようにすることもできます。

$stmt = $conn->prepare('
    INSERT INTO
        password_reset (user_id, temp_password, expiry_date) 
    VALUES
        (:user_id, :temp_password, now() + INTERVAL 3 DAY)
');
$insertResult = $stmt->execute(array(
    ":user_id" => $member_user_id,
    ":temp_password" => $random_password)
);

プリペアド ステートメントを使用する場合、ステートメントはデータをプラグインするためのテンプレートと考える必要があります。

次の構造のデータベース テーブルがある場合:

user_id           INT
temp_password     VARCHAR(128)
expiry_date       DATE

テーブルには3 つの列があります。これらの列に挿入する値のうち 2 つは PHP から取得され、もう 1 つは SQL によって評価されます。SQL は expiry_date 列ですべての作業を行うため、PHP で何かにバインドする必要はありません。

したがって、INSERTステートメントを調べます。

INSERT INTO password_reset (user_id, temp_password, expiry_date) VALUES (:user_id, :temp_password, now() + INTERVAL 3 DAY)

句の各パラメータは、VALUES()句で宣言された列名と一致する必要がありますINSERT INTO table (columns...)

プリペアド ステートメントでは、テンプレートを作成しているため、placeholders実行時にステートメントに値を挿入する場所を示すために を使用します。プレースホルダーは、:name使用したバージョン、または単に疑問符のいずれか?です。

PDO::prepare($statement)SQL サーバーにステートメントを準備するように指示します。その時点で、SQL にはクエリのテンプレートがあり、そのクエリのプレースホルダーの値を受け取る準備ができています。

PDOStatement::execute($placeholderValues)は、その準備されたステートメントの単一のインスタンスを実行し、プレースホルダーを 、 でバインドした値、または に引数として渡した値にbindParam置き換えbindValueますexecute()

したがって、基本的に、execute()クエリ文字列全体ではなく、プレースホルダーにプラグインする値だけがそれぞれの SQL サーバーに送信されます。

次に、なぜできなかったのかを説明する部分が来ますbindValue(":expiry_date", "now() + INTERVAL 3 DAY")

値が SQL サーバーに到達すると、SQL サーバーはそれらをサニタイズし、それぞれのプレースホルダーをその値に置き換えます。

をバインドする"now() + INTERVAL 3 DAY"と、実際には文字列がバインドされます。これは文字列であるため、SQL コードとして実行されません。

于 2013-01-29T16:51:47.773 に答える