如何在 mySQL 版本 8.0.28-cll-lve 中正确使用 group_concat 和 json_array()
How to correctly use group_concat with json_array() in mySQL ver 8.0.28-cll-lve
场景
我希望 SELECT 来自具有简单 varchar 和整数列的 table 和 return 整个 table 的 JSON 表示。这是为了稍后我可以使用 PhP 的 curl() 将 'table' 发送到另一台服务器并重建它。我在我的 ISP 托管的远程共享服务器上使用 MySQL ver 8.0.28-cll-lve。我没有对服务器本身的管理员访问权限,只有使用和维护数据库的所有访问权限。
我试过的
下面的代码和 Stack Exchange 'Database Administrators' 上的 SQLfiddle in response to this post 以及 SO 上完全相同主题的其他几个 post 代码(我不会'不要把它们都列出来,因为我希望第一个回复会告诉我这个问题重复了它们)
应该有效的示例代码
DROP TABLE IF EXISTS contact;
CREATE TABLE contact
(
name_field VARCHAR (5) NOT NULL,
address_field VARCHAR (20) NOT NULL,
contact_age INTEGER NOT NULL
);
INSERT INTO contact
VALUES
('Mary', 'address one', 25),
('Fred', 'address two', 35),
('Bill', 'address three', 47);
SELECT
CONCAT
('[', REPLACE
(
REPLACE
(
GROUP_CONCAT
(
JSON_ARRAY
(
'name_field:', name_field,
'address_field:', address_field,
'age_field:', contact_age
) SEPARATOR ','
), '[', '{'
), ']', '}'
), ']'
)
AS best_result2
FROM contact
在 MySQL 8.0
下 SQL fiddle 中使用此代码的结果 运行
[{"name_field:", "Mary", "address_field:", "address one", "age_field:", 25},{"name_field:", "Fred", "address_field:", "address two", "age_field:", 35},{"name_field:", "Bill", "address_field:", "address three", "age_field:", 47}]
问题
当我 运行 SQL fiddle 中的这段代码使用 mySQL ver 8.0 时,它会产生上面的正确结果。但是,如果我 copy/paste 来自 SQLfiddle 的代码进入 SQLyog 12.4.3 和 运行 它针对 MySQL 数据库版本 8.0.28 -cll-lve 我得到以下语法错误
Error Code: 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 'SEPARATOR ','
我觉得代码没问题。任何人都可以找到原因吗?
编辑 - 更奇怪
感谢 forpas,但我看不出他的代码和我的代码有什么区别,给出了语法错误
作为实验,我将所有代码放在一行中 - 仍然出现错误
然后我删除了除 SELECT、AS 和 FROM 之后的所有 spaces 并且它工作正常。我只能假设 space 放在错误的位置会破坏语法,尽管这似乎不太可能。
编辑 2 - 已解决,语法错误的原因
感谢所有指出我使用的代码未生成有效代码的人 JSON。这不是重点,它产生了一些东西,而不是语法错误,所以与我的问题有点无关。该代码来自数据库管理员的一个公认答案,因为它在 SDQLfiddle 中工作而没有语法错误,我认为它可以在我的 DBMS 中工作(我没有注意到 JSON 在时间,但我可以稍后轻松修复)。
但是用户 forpas 对我为什么会收到语法错误的问题给出了正确的答案,这是 copy/paste 操作在 GROUP_CONCAT 和它的中间放置了一个 space下面的括号。删除 space 和代码 运行s 没有语法错误。
Result of running this code in SQL fiddle under MySQL 8.0
[{"name_field:", "Mary", "address_field:", "address one", "age_field:", 25},{"name_field:", "Fred", "address_field:", "address two", "age_field:", 35},{"name_field:", "Bill", "address_field:", "address three", "age_field:", 47}]
这是无效的 JSON。这是一些 JSON-like 字符串。
测试这对你来说是否安全:
SELECT JSON_ARRAYAGG(JSON_OBJECT('name_field', name_field,
'address_field', address_field,
'contact_age', contact_age)) all_contacts
FROM contact;
精确提供所需输出的代码:
SELECT CONCAT('[',
GROUP_CONCAT(
CONCAT(
'{',
CONCAT_WS(', ',
'"name_field:"', JSON_QUOTE(name_field),
'"address_field:"', JSON_QUOTE(address_field),
'"age_field:"', contact_age
),
'}'
)
),
']'
) one_value
FROM contact
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=568f2f8f0ef7e6dfb10941b7469fa0db
您的问题实际上记录在 Function Name Parsing and Resolution/Built-In Function Name Parsing:
The parser uses default rules for parsing names of built-in functions.
These rules can be changed by enabling the IGNORE_SPACE SQL mode.
When the parser encounters a word that is the name of a built-in
function, it must determine whether the name signifies a function call
or is instead a nonexpression reference to an identifier such as a
table or column name....
some built-in functions have special parsing or implementation
considerations, so the parser uses the following rules by default to
distinguish whether their names are being used as function calls or as
identifiers in nonexpression context:
To use the name as a function call in an expression, there must be no
whitespace between the name and the following ( parenthesis character.
Conversely, to use the function name as an identifier, it must not be
followed immediately by a parenthesis
函数 GROUP_CONCAT()
属于受 IGNORE_SPACE 设置影响的函数列表。
因此,删除 GROUP_CONCAT
和 (
之间的任何间距。
参见demo。
场景
我希望 SELECT 来自具有简单 varchar 和整数列的 table 和 return 整个 table 的 JSON 表示。这是为了稍后我可以使用 PhP 的 curl() 将 'table' 发送到另一台服务器并重建它。我在我的 ISP 托管的远程共享服务器上使用 MySQL ver 8.0.28-cll-lve。我没有对服务器本身的管理员访问权限,只有使用和维护数据库的所有访问权限。
我试过的
下面的代码和 Stack Exchange 'Database Administrators' 上的 SQLfiddle in response to this post 以及 SO 上完全相同主题的其他几个 post 代码(我不会'不要把它们都列出来,因为我希望第一个回复会告诉我这个问题重复了它们)
应该有效的示例代码
DROP TABLE IF EXISTS contact;
CREATE TABLE contact
(
name_field VARCHAR (5) NOT NULL,
address_field VARCHAR (20) NOT NULL,
contact_age INTEGER NOT NULL
);
INSERT INTO contact
VALUES
('Mary', 'address one', 25),
('Fred', 'address two', 35),
('Bill', 'address three', 47);
SELECT
CONCAT
('[', REPLACE
(
REPLACE
(
GROUP_CONCAT
(
JSON_ARRAY
(
'name_field:', name_field,
'address_field:', address_field,
'age_field:', contact_age
) SEPARATOR ','
), '[', '{'
), ']', '}'
), ']'
)
AS best_result2
FROM contact
在 MySQL 8.0
下 SQL fiddle 中使用此代码的结果 运行[{"name_field:", "Mary", "address_field:", "address one", "age_field:", 25},{"name_field:", "Fred", "address_field:", "address two", "age_field:", 35},{"name_field:", "Bill", "address_field:", "address three", "age_field:", 47}]
问题
当我 运行 SQL fiddle 中的这段代码使用 mySQL ver 8.0 时,它会产生上面的正确结果。但是,如果我 copy/paste 来自 SQLfiddle 的代码进入 SQLyog 12.4.3 和 运行 它针对 MySQL 数据库版本 8.0.28 -cll-lve 我得到以下语法错误
Error Code: 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 'SEPARATOR ','
我觉得代码没问题。任何人都可以找到原因吗?
编辑 - 更奇怪
感谢 forpas,但我看不出他的代码和我的代码有什么区别,给出了语法错误 作为实验,我将所有代码放在一行中 - 仍然出现错误 然后我删除了除 SELECT、AS 和 FROM 之后的所有 spaces 并且它工作正常。我只能假设 space 放在错误的位置会破坏语法,尽管这似乎不太可能。
编辑 2 - 已解决,语法错误的原因
感谢所有指出我使用的代码未生成有效代码的人 JSON。这不是重点,它产生了一些东西,而不是语法错误,所以与我的问题有点无关。该代码来自数据库管理员的一个公认答案,因为它在 SDQLfiddle 中工作而没有语法错误,我认为它可以在我的 DBMS 中工作(我没有注意到 JSON 在时间,但我可以稍后轻松修复)。
但是用户 forpas 对我为什么会收到语法错误的问题给出了正确的答案,这是 copy/paste 操作在 GROUP_CONCAT 和它的中间放置了一个 space下面的括号。删除 space 和代码 运行s 没有语法错误。
Result of running this code in SQL fiddle under MySQL 8.0
[{"name_field:", "Mary", "address_field:", "address one", "age_field:", 25},{"name_field:", "Fred", "address_field:", "address two", "age_field:", 35},{"name_field:", "Bill", "address_field:", "address three", "age_field:", 47}]
这是无效的 JSON。这是一些 JSON-like 字符串。
测试这对你来说是否安全:
SELECT JSON_ARRAYAGG(JSON_OBJECT('name_field', name_field,
'address_field', address_field,
'contact_age', contact_age)) all_contacts
FROM contact;
精确提供所需输出的代码:
SELECT CONCAT('[',
GROUP_CONCAT(
CONCAT(
'{',
CONCAT_WS(', ',
'"name_field:"', JSON_QUOTE(name_field),
'"address_field:"', JSON_QUOTE(address_field),
'"age_field:"', contact_age
),
'}'
)
),
']'
) one_value
FROM contact
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=568f2f8f0ef7e6dfb10941b7469fa0db
您的问题实际上记录在 Function Name Parsing and Resolution/Built-In Function Name Parsing:
The parser uses default rules for parsing names of built-in functions. These rules can be changed by enabling the IGNORE_SPACE SQL mode.
When the parser encounters a word that is the name of a built-in function, it must determine whether the name signifies a function call or is instead a nonexpression reference to an identifier such as a table or column name....
some built-in functions have special parsing or implementation considerations, so the parser uses the following rules by default to distinguish whether their names are being used as function calls or as identifiers in nonexpression context:
To use the name as a function call in an expression, there must be no whitespace between the name and the following ( parenthesis character.
Conversely, to use the function name as an identifier, it must not be followed immediately by a parenthesis
函数 GROUP_CONCAT()
属于受 IGNORE_SPACE 设置影响的函数列表。
因此,删除 GROUP_CONCAT
和 (
之间的任何间距。
参见demo。