尝试了我能想到的一切,我已经缩小到“?”占位符。
我试过更换“?”带有随机文本的占位符,一切运行良好(当然除了它会覆盖同一行)。
我得到的错误:
您的SQL语法有错误;检查与MySQL服务器版本对应的手册,以便在“?,?,?,?,?,?,?,?,?,?,?,?”附近使用正确的语法 在DUPLICATE KEY UPDATE 产品'在第2行
这是我的代码(我会提供更多,但除了这个bug之外它都运行良好,如果我删除“?”占位符,那么除了值不是动态的,所有的工作都很完美,但请问你是否怀疑问题在别处):
// Create MySQL connection to ds_signifyd_api
$mysqli = mysqli_connect( $db_server_name, $db_username, $db_password, $db_name );
// Check connection
if ($mysqli->connect_error) {
exit( $mysqliFailedBody );
}
$mainProdQueryStmt = "INSERT INTO products (`product_id`, `title`, `body_html`, `vendor`, `product_type`, `created_at`, `handle`, `updated_at`, `published_at`, `template_suffix`, `published_scope`, `tags`)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
product_id = VALUES(product_id),
title = VALUES(title),
body_html = VALUES(body_html),
vendor = VALUES(vendor),
product_type = VALUES(product_type),
created_at = VALUES(created_at),
handle = VALUES(handle),
updated_at = VALUES(updated_at),
published_at = VALUES(published_at),
template_suffix = VALUES(template_suffix),
published_scope = VALUES(published_scope),
tags = VALUES(tags)";
$product_id = $product_title = $body_html = $vendor = $product_type = $created_at = $handle = $updated_at = $published_at = $template_suffix = $published_scope = $tags = "";
foreach ($dss_product_db_array as $product) {
$product_id = $product['id'];
//... more variables here...
$tags = mysqli_real_escape_string($mysqli, $tags);
if (!mysqli_query($mysqli, $mainProdQueryStmt)) {
printf("Errormessage: %s\n", mysqli_error($mysqli));
}
$mainProdQuery->bind_param("isssssssssss", $product_id, $product_title, $body_html, $vendor, $product_type, $created_at,
$handle, $updated_at, $published_at, $template_suffix, $published_scope, $tags);
$mainProdQuery->execute();
// $mainProdQuery->close();
}
实现了此处提到的修复:
1.停止使用mysqli_real_escape_string
2.在循环外绑定变量
3.仅使用面向对象的方法,而不是像mysqli_query($mysqli, $mainProdQueryStmt)
VS $mysqli->prepare($mainProdQueryStmt)
那样将它们混合在一起 - 这就解决了“?”占位符语法错误报告错误
现在一切都很完美,没有错误。
更新代码:
$mainProdQueryStmt = "INSERT INTO dss_products (`product_id`, `title`, `body_html`, `vendor`, `product_type`, `created_at`, `handle`, `updated_at`, `published_at`, `template_suffix`, `published_scope`, `tags`)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
product_id = VALUES(product_id),
title = VALUES(title),
body_html = VALUES(body_html),
vendor = VALUES(vendor),
product_type = VALUES(product_type),
created_at = VALUES(created_at),
handle = VALUES(handle),
updated_at = VALUES(updated_at),
published_at = VALUES(published_at),
template_suffix = VALUES(template_suffix),
published_scope = VALUES(published_scope),
tags = VALUES(tags)";
$mainProdQuery = $mysqli->prepare($mainProdQueryStmt);
if ($mainProdQuery === FALSE) {
die($mysqli->error);
}
$product_id = $product_title = $body_html = $vendor = $product_type = $created_at = $handle = $updated_at = $published_at = $template_suffix = $published_scope = $tags = "";
$mainProdQuery->bind_param("isssssssssss", $product_id, $product_title, $body_html, $vendor, $product_type, $created_at,
$handle, $updated_at, $published_at, $template_suffix, $published_scope, $tags);
if ($mainProdQuery) {
foreach ($dss_product_db_array as $product) {
$product_id = $product['id'];
$product_title = $product['title'];
$body_html = $product['body_html'];
$vendor = $product['vendor'];
$product_type = $product['product_type'];
$created_at = $product['created_at'];
$handle = $product['handle'];
$updated_at = $product['updated_at'];
$published_at = $product['published_at'];
$template_suffix = $product['template_suffix'];
$published_scope = $product['published_scope'];
$tags = $product['tags'];
if (!$mysqli->prepare($mainProdQueryStmt)) {
printf("Errormessage: %s\n", $mysqli->error);
}
$mainProdQuery->execute();
}
}
答案 0 :(得分:3)
使用占位符时必须使用mysqli_prepare()
,不能使用mysqli_query()
。看起来你打算这样做,但不知何故代码丢失了,因为你使用了一个你从未分配过的变量$mainProdQuery
。
您应该准备查询并在循环外绑定参数一次。然后在循环内调用execute()
。
$mainProdQueryStmt = "INSERT INTO products (`product_id`, `title`, `body_html`, `vendor`, `product_type`, `created_at`, `handle`, `updated_at`, `published_at`, `template_suffix`, `published_scope`, `tags`)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
product_id = VALUES(product_id),
title = VALUES(title),
body_html = VALUES(body_html),
vendor = VALUES(vendor),
product_type = VALUES(product_type),
created_at = VALUES(created_at),
handle = VALUES(handle),
updated_at = VALUES(updated_at),
published_at = VALUES(published_at),
template_suffix = VALUES(template_suffix),
published_scope = VALUES(published_scope),
tags = VALUES(tags)";
$mainProdQuery = $mysqli->prepare($mainProdQueryStmt);
$mainProdQuery->bind_param("isssssssssss", $product_id, $product_title, $body_html, $vendor, $product_type, $created_at,
$handle, $updated_at, $published_at, $template_suffix, $published_scope, $tags);
foreach ($dss_product_db_array as $product) {
$product_id = $product['id'];
//... more variables here...
$mainProdQuery->execute();
}
答案 1 :(得分:1)
您在正确准备之前运行查询,然后,在事实之后,尝试绑定到不正确类型的内容,它不是语句句柄而是结果集。你需要以这种方式构建它:
$mainProdQueryStmt = "INSERT INTO products (`product_id`, `title`, `body_html`, `vendor`, `product_type`, `created_at`, `handle`, `updated_at`, `published_at`, `template_suffix`, `published_scope`, `tags`)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
product_id = VALUES(product_id),
...
tags = VALUES(tags)";
// Prepare the statement to get a statement handle
$stmt = $mysqli->prepare($mainProdQueryStmt);
foreach ($dss_product_db_array as $product) {
// Bind to this statement handle the raw values (non-escaped)
$stmt->bind_param("isssssssssss",
$product['id'], $product['title'], ...);
// Execute the query
$stmt->execute();
}
尽量避免创建大量的丢弃变量,只需将直接绑定到有问题的值,就像$product
中那样。变量没有任何用处,只会为愚蠢的错误带来机会。
答案 2 :(得分:-1)
尝试使用PDO(PhP Data Objects)准备好的语句。使用和交叉数据库不那么痛苦,即可以与任何RDBMS一起使用。请参阅PDO Official Documentation或here