MySQL 使用 JSON 数组作为值时的语法错误
MySQL Syntax Error when using JSON array as value
我的Table:
- customer_id INT(主键)
- purchased_products JSON
- refunded_products = JSON
预期值
- 12345
- ["32","33","34"]
- ["31","38","39"]
以下 SQL 按预期工作。太棒了!
-- Insert a new row into the purchased products table
INSERT INTO dc_purchased_products (
user_id, -- INT
purchased_products -- JSON
)
-- 1) The user ID (primary key)
-- 2) Formatted json array with the first purchased product ID
VALUES ( 12345, '["36"]' )
-- If the user id already exists, append the existing array with the product ID
ON DUPLICATE KEY UPDATE
-- JSON_ARRAY_INSERT(existing purchases array, index, product_id)
purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]', "36")
但是,我的应用程序中的 PDO 声明不是很好。
$item = [
'statement' => "INSERT INTO purchased_products
(customer_id, purchased_products)
VALUES(:customer_id, [:purchased_products])
ON DUPLICATE KEY
UPDATE purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products)",
'data' => [
['customer_id' => 12345, 'purchased_products' => '"36"'],
['customer_id' => 12345, 'purchased_products' => '"37"']
]
]
我的连接
$this->connection = new PDO("mysql:host=$servername;dbname=$database", $u, $p, [
PDO::MYSQL_ATTR_SSL_KEY => $ck,
PDO::MYSQL_ATTR_SSL_CERT => $cc,
PDO::MYSQL_ATTR_SSL_CA => $sc,
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
]);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $this->connection->prepare($item['statement']);
foreach ($item['data'] as $rowData) {
foreach ($rowData as $key => $param) {
$statement->bindValue(':' . $key, $param);
}
try {
$success = $statement->execute();
}
catch (PDOException $e) {
pre($e->getMessage());
}
}
错误信息
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '['3784835']) ON DUPLICATE KEY UPDATE purchased_products = JSON_ARRAY_INSERT(purc' at line 1
这应该可以解决问题:
$item = [
'statement' => "INSERT INTO purchased_products
(customer_id, purchased_products)
VALUES(:customer_id, :purchased_products)
ON DUPLICATE KEY
UPDATE purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products_json)",
'data' => [
['customer_id' => 12345, 'purchased_products' => '["36"]', 'purchased_products_json' => '36'],
['customer_id' => 12345, 'purchased_products' => '["37"]', 'purchased_products_json' => '37'],
]
];
更改说明:
在 VALUES(:customer_id, [:purchased_products])
中删除了 [
和 ]
现在看起来像这样:
VALUES(:customer_id, :purchased_products)
此更改将避免 execute()
期间的错误。
JSON_ARRAY_INSERT 中的新参数:purchased_products_json
现在看起来像这样:
JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products_json)
为了避免这个错误,我们现在需要两个差异很小的参数。一个用于插入 (purchased_products
),另一个用于更新 (purchased_produtcs_json
),因为尽管值相同,但格式不同。
在data
数组中,改为'purchased_products' => '"36"'
现在看起来像这样:
'purchased_products' => '["36"]'
因为我们将在 INSERT 语句中使用它,我们需要将其设置为具有正确格式的新 JSON 数组值,并且因为我们已经删除了 [
和 ]
之前的 INSERT 语句。
在data
数组中,添加了新参数:'purchased_products_json'
为了更新字段,值格式应该不同,所以我们需要这个新参数。看起来像这样:
'purchased_products_json' => '36'
避免使用 [
和 ]
。您可以在 mariadb documentation
中查看有关 JSON_ARRAY_INSERT 的一些信息
我的Table:
- customer_id INT(主键)
- purchased_products JSON
- refunded_products = JSON
预期值
- 12345
- ["32","33","34"]
- ["31","38","39"]
以下 SQL 按预期工作。太棒了!
-- Insert a new row into the purchased products table
INSERT INTO dc_purchased_products (
user_id, -- INT
purchased_products -- JSON
)
-- 1) The user ID (primary key)
-- 2) Formatted json array with the first purchased product ID
VALUES ( 12345, '["36"]' )
-- If the user id already exists, append the existing array with the product ID
ON DUPLICATE KEY UPDATE
-- JSON_ARRAY_INSERT(existing purchases array, index, product_id)
purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]', "36")
但是,我的应用程序中的 PDO 声明不是很好。
$item = [
'statement' => "INSERT INTO purchased_products
(customer_id, purchased_products)
VALUES(:customer_id, [:purchased_products])
ON DUPLICATE KEY
UPDATE purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products)",
'data' => [
['customer_id' => 12345, 'purchased_products' => '"36"'],
['customer_id' => 12345, 'purchased_products' => '"37"']
]
]
我的连接
$this->connection = new PDO("mysql:host=$servername;dbname=$database", $u, $p, [
PDO::MYSQL_ATTR_SSL_KEY => $ck,
PDO::MYSQL_ATTR_SSL_CERT => $cc,
PDO::MYSQL_ATTR_SSL_CA => $sc,
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
]);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $this->connection->prepare($item['statement']);
foreach ($item['data'] as $rowData) {
foreach ($rowData as $key => $param) {
$statement->bindValue(':' . $key, $param);
}
try {
$success = $statement->execute();
}
catch (PDOException $e) {
pre($e->getMessage());
}
}
错误信息
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '['3784835']) ON DUPLICATE KEY UPDATE purchased_products = JSON_ARRAY_INSERT(purc' at line 1
这应该可以解决问题:
$item = [
'statement' => "INSERT INTO purchased_products
(customer_id, purchased_products)
VALUES(:customer_id, :purchased_products)
ON DUPLICATE KEY
UPDATE purchased_products = JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products_json)",
'data' => [
['customer_id' => 12345, 'purchased_products' => '["36"]', 'purchased_products_json' => '36'],
['customer_id' => 12345, 'purchased_products' => '["37"]', 'purchased_products_json' => '37'],
]
];
更改说明:
在 VALUES(:customer_id, [:purchased_products])
[
和 ]
现在看起来像这样:
VALUES(:customer_id, :purchased_products)
此更改将避免 execute()
期间的错误。
JSON_ARRAY_INSERT 中的新参数:purchased_products_json
现在看起来像这样:
JSON_ARRAY_INSERT(purchased_products, '$[0]',:purchased_products_json)
为了避免这个错误,我们现在需要两个差异很小的参数。一个用于插入 (purchased_products
),另一个用于更新 (purchased_produtcs_json
),因为尽管值相同,但格式不同。
在data
数组中,改为'purchased_products' => '"36"'
现在看起来像这样:
'purchased_products' => '["36"]'
因为我们将在 INSERT 语句中使用它,我们需要将其设置为具有正确格式的新 JSON 数组值,并且因为我们已经删除了 [
和 ]
之前的 INSERT 语句。
在data
数组中,添加了新参数:'purchased_products_json'
为了更新字段,值格式应该不同,所以我们需要这个新参数。看起来像这样:
'purchased_products_json' => '36'
避免使用 [
和 ]
。您可以在 mariadb documentation