【问题标题】:INSERT statement with 'now() + INTERVAL' inserts 000's in PDO with named placeholders带有“now() + INTERVAL”的 INSERT 语句在 PDO 中插入 000,并带有命名占位符
【发布时间】:2013-01-13 07:32:41
【问题描述】:

我无法将此now() + INTERVAL INSERT 语句转换为带有命名占位符的 PDO 准备语句。

当我使用'now() + INTERVAL 3 DAY''DATE_ADD(now(), INTERVAL 3 DAY)' 绑定值时,它会插入000 而不是正确的日期时间(0000-00-00 00:00:00)

这是我之前使用的:

$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 帖子(包括这个 link 建议将 now() 语句放在 VALUES 中而不是绑定它,但这会导致错误消息 'Invalid parameter number: number绑定变量的数量与标记的数量不匹配'

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

【问题讨论】:

  • :now() + INTERVAL 3 DAY 中删除:。您还应该使用bindParam 而不是bindValue
  • 如果它清楚地写着'Invalid parameter number: number of bound variables does not match number of tokens' - 为什么不计算冒号的数量?
  • @crush - 在第 42 行的 /home4/clickfi4/public_html/demo/forgotpass-exec.php 中生成错误消息“解析错误:语法错误,意外 ':',期待 ')' "
  • @YourCommonSense - 你能详细说明一下吗?我一直认为 INSERT、VALUE 和 bindValue 语句中的变量数量应该相同,所以我假设这种方法的问题是它们的数量不匹配。
  • @ChayaCooper 这与使用正确的术语无关。 INSERTVALUES() 部分中应该有三个变量,因为那是有多少列。但是,这些列中只有两列是 bound 使用 bindValue 方法的列。由于您最初有 3 个绑定列,但只为其中两个绑定列分配值,因此您收到了 Your Common Sense 显示的错误。

标签: php mysql datetime insert pdo


【解决方案1】:

: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

您的表格中有三列插入这些列的两个值将来自 PHP另一个将由 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) 执行该准备好的语句的单个实例,将占位符替换为您与bindParambindValue 绑定的值,或作为参数传递给execute()

因此,基本上,每个execute() 上发送到 SQL 服务器的所有内容都是插入占位符的值,而不是整个查询字符串。

现在是解释为什么你不能bindValue(":expiry_date", "now() + INTERVAL 3 DAY")的部分。

当值到达 SQL Server 时,SQL Server 会对它们进行清理并用它们的值替换相应的占位符。

当您绑定"now() + INTERVAL 3 DAY" 时,您实际上是在绑定一个字符串。由于它是一个字符串,它不会作为 SQL 代码执行。

【讨论】:

  • 任何人都不应使用bindParam 而不是bindValue。你把东西弄混了。如果您建议使用一种功能而不是另一种功能,请提供您认为这样做更好的理由。
  • 你是对的。起初我将 bindValue 与 bindColumn 混淆了。 bindParam():Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.
  • 删除冒号会产生这个错误“解析错误:语法错误,意外':',期待')'”。我现在就试试你的第二个建议...
  • VALUES(:user_id, :temp_password, now() + INTERVAL 3 DAY)');
  • 我刚刚创建了一个模仿你的表格,并进行了测试,它对我来说工作正常。请仔细检查您的代码是否与我上面的代码相同。
【解决方案2】:

:now()前面有一个冒号
而已。只是一个错字。

您的第二条错误消息清楚地表明您实际上并没有删除冒号,而是删除了其他内容 - 很可能是引号。你需要更加注意写作。并更加注意错误消息,它们非常有用。

【讨论】:

  • 删除冒号会产生这个错误“解析错误:语法错误,意外':',期待')'”
  • 这很奇怪 - 我肯定删除了冒号(我检查了三次)并收到了该错误消息,但是当我复制并粘贴 @crush 的完整代码时(而不仅仅是需要的行要改变)它的工作!我希望我能理解为什么有时会发生这种情况,但我很高兴它现在正在起作用,并且这种逻辑再次盛行:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
  • 2016-03-02
  • 2012-12-14
  • 2019-09-15
  • 2015-07-10
  • 1970-01-01
相关资源
最近更新 更多