【问题标题】:Sprintf inserting NULL into mysqlSprintf将NULL插入mysql
【发布时间】:2018-05-15 09:00:32
【问题描述】:

早上好,拼命尝试解决我在 MySQL 5.7.19 中插入空白日期值时遇到的问题,3 天后转向这里寻求帮助。

数据库设置为允许 NULL - 默认 NULL 有时会填充前端字段,通常不是这样的空值。

错误弹出:

无法执行 SQL 语句:日期值不正确:'' for column 'signedupdate' at row 1

插入

$lastInsertId = $this->GetConnection()->GetLastInsertId();
$sql = sprintf("INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES(%d, '%s', '%s');", $lastInsertId, $rowData['signedupdate'], $rowData['plan_type']);
$this->GetConnection()->ExecSQL($sql);

更新

$sql = sprintf("UPDATE tbl_lead SET signedupdate = '%s', plan_type = '%s'WHERE client_id = %d;", $rowData['signedupdate'], $rowData['plan_type']);
$this->GetConnection()->ExecSQL($sql);

谁能看出我哪里出错了?

【问题讨论】:

  • 我鼓励你使用准备好的语句来防止sql注入。
  • var_dump($lastInsertId, $rowData['signedupdate'], $rowData['plan_type']) 的输出是什么?
  • 测试您传递的每个参数,%s 将需要一个字符串类型,尝试使用 is_string 在 sprintf 之前添加测试以验证它们的类型是否正确。
  • 如果你不想为一个字段插入一个值,并且它有一个默认值(甚至是NULL),只需在插入语句中跳过它。不要传递作为值(空白但仍然是值)的 '' 并将根据该字段的数据类型进行评估:如果它是一个日期,它将失败

标签: php mysql printf


【解决方案1】:

在执行之前尝试回显查询字符串,然后在 phymyadmin 中复制/粘贴回显的查询并检查查询中的错误

$lastInsertId = $this->GetConnection()->GetLastInsertId();
$sql = sprintf("INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES(%d, '%s', '%s');", $lastInsertId, $rowData['signedupdate'], $rowData['plan_type']);
echo $sql;

$this->GetConnection()->ExecSQL($sql);

【讨论】:

  • 我在 phpmyadmin 中运行它并收到以下错误。所以看起来 '' 不被接受,但 NULL 被接受,并且 0000-01-01 被接受。 我真的需要它作为 NULL 以避免在稍后阶段出现报告问题,但不能完全理解为什么 php 作为字符串插入?
    'INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES(20943, '', '');{"success":false,"message":"无法执行 SQL 语句:日期值不正确: '' 用于第 1 行的列 'signedupdate'","messageDisplayTime":0}'
【解决方案2】:

在 SQL(如 PHP)中,NULL 值与恰好具有字母 N-U-L-L 的常规文本变量之间存在很大差异。只要源变量是实际的null(而不是文本'null')并且您按预期使用该库,这将由任何体面的数据库库自动处理。

您正在使用自定义的自定义数据库库,因此很难说是哪种情况。如果库还不错,它应该提供如下语法:

$sql = 'INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES (?, ?, ?)';
$this->GetConnection()->ExecSQL($sql, [
    $lastInsertId,
    $rowData['signedupdate'],
    $rowData['plan_type']
]);

当然,不一定是this语法。源码请参考库文档。

如果它是一个糟糕的库,它只会提供转义函数。如果这些函数自动添加引号,您可能会很幸运,例如:

$sql = sprintf('INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES(%s, %s, %s)',
    $this->GetConnection()->EscapeValue($lastInsertId),
    $this->GetConnection()->EscapeValue($rowData['signedupdate']),
    $this->GetConnection()->EscapeValue($rowData['plan_type'])
);
$this->GetConnection()->ExecSQL($sql);

再一次,我只是编造了语法。

否则,您将不得不自己处理所有事情:

$sql = sprintf('INSERT INTO tbl_lead (client_id, signedupdate, plan_type) VALUES(%s, %s, %s)',
    $lastInsertId===null ? 'NULL' : "'" . $this->GetConnection()->EscapeValue($lastInsertId) . "'",
    $rowData['signedupdate']===null ? 'NULL' : "'" . $this->GetConnection()->EscapeValue($rowData['signedupdate']) . "'",
    rowData['plan_type']===null ? 'NULL' : "'" . $this->GetConnection()->EscapeValue($rowData['plan_type']) . "'"
);
$this->GetConnection()->ExecSQL($sql);

如果库甚至不提供转义功能,您应该真正停下来并切换到例如PDO。无论如何,切换甚至可能是一个好主意——根据我的经验,StrangelyCasedLibraries() 的质量往往令人怀疑。

【讨论】:

    猜你喜欢
    • 2019-04-28
    • 1970-01-01
    • 2012-09-11
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多