带有位置占位符的 ON DUPLICATE KEY UPDATE 的语法

Posted

技术标签:

【中文标题】带有位置占位符的 ON DUPLICATE KEY UPDATE 的语法【英文标题】:Syntax for ON DUPLICATE KEY UPDATE with positional placeholders 【发布时间】:2013-05-14 05:24:48 【问题描述】:

这是REPLACE 语法

$sql = "REPLACE INTO 2_1_journal (Number,RecordDay, RecordMonth) VALUES ";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];
$insertData[] = $_POST['date_month'][$i];

if (!empty($insertQuery)) 
$sql .= implode(', ', $insertQuery);
$stmt = $db->prepare($sql);
$stmt->execute($insertData);

但是请阅读而不是 REPLACE 更好地使用 ON DUPLICATE KEY UPDATE

试着像这样改变

$sql = "INSERT INTO 2_1_journal (Number,RecordDay, RecordMonth) VALUES ON DUPLICATE KEY UPDATE (RecordDay, RecordMonth) ";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?, ?, ?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];
$insertData[] = $_POST['date_month'][$i];
$insertData[] = $_POST['date_day'][$i];
$insertData[] = $_POST['date_month'][$i];

if (!empty($insertQuery)) 
$sql .= implode(', ', $insertQuery);
$stmt = $db->prepare($sql);
$stmt->execute($insertData);

但不起作用(既不插入也不更新)

什么不正确?

如果投反对票,请在 cmets 中写下原因(为我避免写导致投反对票的内容)

更新

代码改成这个

$sql = "INSERT INTO 2_1_journal (Number, RecordDay) VALUES ON DUPLICATE KEY UPDATE RecordDay";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];

get SQLSTATE[42000]: 语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 mysql 服务器版本相对应的手册,以在第 1 行的 'ON DUPLICATE KEY UPDATE RecordDay('21', ''), ('22', '')' 附近使用正确的语法

改成这个

$sql = "INSERT INTO 2_1_journal (Number, RecordDay) VALUES ON DUPLICATE KEY UPDATE RecordDay=VALUES(Number)";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];

get SQLSTATE[42000]: 语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“ON DUPLICATE KEY UPDATE RecordDay=VALUES(Number)('21', ''), ('22', '')' 附近使用正确的语法

代码改成这个

$sql = "INSERT INTO 2_1_journal (Number, RecordDay) VALUES ON DUPLICATE KEY UPDATE RecordMonth=?";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];
$insertData[] = $_POST['date_month'][$i];

get SQLSTATE[HY093]: Invalid parameter number: 绑定变量数与token数不匹配

我能否得出结论,最后一个示例是有效的 SQL 语法。但为什么会出错?编号、记录日、记录月=?和$insertQuery[] = '(?, ?, ?)'; 3 个变量和 3 个令牌?还是我错了?

如果$insertQuery[] = '(?, ?)';相同 SQLSTATE[HY093]: 参数号无效:绑定变量的数量与标记的数量不匹配

请帮忙。我被卡住了……不知道

工作代码!!!

try 
$sql = "INSERT INTO 2_1_journal (Number, RecordDay) VALUES ";
$insertQuery = array();
$insertData = array();
foreach ($_POST['row_id'] as $i => $row_id) 
$insertQuery[] = '(?, ?)';
$insertData[] = $row_id;
$insertData[] = $_POST['date_day'][$i];

if (!empty($insertQuery)) 
$sql .= implode(', ', $insertQuery) . 'ON DUPLICATE KEY UPDATE RecordDay = VALUES(RecordDay);';
$stmt = $db->prepare($sql);
$stmt->execute($insertData);


catch (PDOException $e)
echo "DataBase Error: " .$e->getMessage() .'<br>';

catch (Exception $e) 
echo "General Error: ".$e->getMessage() .'<br>';

请你们的cmets。并查看ON DUPLICATE KEY UPDATE的位置!!!

【问题讨论】:

在将其放入prepare 之前,您是否检查过最终查询的样子?这根本不构成任何类型的有效 SQL 查询。投反对票的一个原因是您应该自己进行更多实验,这只是以正确的顺序连接字符串。 您是否收到任何错误消息?如果是,那是什么? 而且您的查询很容易受到 sql 注入的影响。至少对于新手或计算机怪人来说,花点时间让它更安全 @deceze 查询在 mysql 中插入与输入表单中输入的相同值 @JW 没有错误消息 @ScoRpion 这是 PDO @deceze 查询在 mysql 中插入与输入表单中输入的相同值跨度> 正确的 SQL 语法应该是INSERT INTO &lt;table&gt; VALUES (?,?,?) ON DUPLICATE KEY UPDATE a=a+1。 dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html 【参考方案1】:

每当你使用代码构建 SQL 语句时,添加一行:

echo $sql;

就在执行语句之前。这样您就可以看到您实际执行的操作。

然后您可以将 SQL 语句直接剪切并粘贴到数据库中,看看会发生什么。

另外——为了防止SQL注入,添加

$row_id = mysql_real_escape_string($POST['row_id']);
$date_day = mysql_real_escape_string($_POST['date_day']);
$date_month = mysql_real_escape_string($_POST['date_month']);

到代码的开头,然后在其余代码中使用 $row_id 而不是 $POST['row_id']。并且 $date_day 而不是 $_POST['date_day'],以及 $date_month 而不是 $_POST['date_month'] 等 - 对所有 POST 和 GET 变量执行此操作。

检查这个: http://xkcd.com/327/

【讨论】:

以上是关于带有位置占位符的 ON DUPLICATE KEY UPDATE 的语法的主要内容,如果未能解决你的问题,请参考以下文章

具有许多占位符的 ItemStack

带有占位符的 FormatMessage

带有模板占位符的 Url Helper 路由

iOS 13 - 带有占位符的 UITextField 让应用程序崩溃

Laravel 数据库选择带有占位符的下拉菜单

带有可选占位符的 string.format()