MySQL 中的 SELECT 和 CONCAT
Posted
技术标签:
【中文标题】MySQL 中的 SELECT 和 CONCAT【英文标题】:SELECT and CONCAT in MySQL 【发布时间】:2021-11-28 13:14:13 【问题描述】:我正在使用 mysql 并尝试将 CONCAT_WS() 函数与 SELECT 一起使用。
我试过了:
SELECT id, A_12, CONCAT_WS('A_', '12') as testA from TABLE_A
我期待类似的东西
id | A_12 | testA |
-------------------
1 | 20 | 20 |
testA
的值应与A_12
中的值相同。
然而,我得到的是
id | A_12 | testA |
-------------------
1 | 20 | 12 |
testA 列中的“12”只是来自 CONCAT_WS() 函数 CONCAT_WS('A_','12')
的后一个字符串。
任何帮助将不胜感激。
======编辑======:
抱歉,我一开始没有明确说明我的问题和目的。我在TABLE_A
中有 12 列 A_1, A_2, ... , A_12
。更具体地说,Table_A
看起来像这样:
id | A_1 | A_2 | ... | A_12|
---------------------------
1 | 4 | 5 | ... | 20 |
2 | 1 | 4 | ... | 50 |
3 | 2 | 5 | ... | 70 |
我还有另一张桌子 TABLE_B
,看起来像这样:
id | value
----------
1 | 12
2 | 5
3 | 3
我正在尝试创建一个存储函数...
-
从
TABLE_B
中选择对应的value
来自TABLE_A
,拉取A_
列下的信息+来自Table_B
的值
对于每个id
。
所以我有
SELECT id, CONCAT_WS('A_', stored-value-from-TABLE_B) as testA from TABLE_A
为了确保代码是否按预期运行,我运行了
SELECT id, A_12, CONCAT_WS('A_', '12') as testA from TABLE_A
因为Table_B
中id=1
的值是12。
但是,我得到的是每个id
的testA
列中的12
。
【问题讨论】:
你为什么期待 20?你想做什么? 不能在sql中动态引用数据库对象。你必须用脚本语言(或存储过程)动态生成你的 sql 语句,然后执行它来做你想做的事情。 为什么不在列名上使用你想要的别名select A_12, A_12 as testA
【参考方案1】:
您可以在 id
s 上加入表格,并使用函数 ELT()
选择正确的 A_?
,您必须在其中枚举所有 12 列:
SELECT b.*,
ELT(b.value, a.A_1, a.A_2, ..., a.A_12) testA
FROM TABLE_B b INNER JOIN TABLE_A a
ON b.id = a.id;
查看简化的demo。
【讨论】:
【参考方案2】:只需要得到这个结果就可以了
SELECT id, A_12, A_12 as testA from TABLE_A
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。您可以在帮助中心找到更多关于如何写好答案的信息:***.com/help/how-to-answer。祝你好运?【参考方案3】:您似乎认为选择列表必然是列名列表,因此像 CONCAT_WS() 这样的字符串函数会产生像 A_12
这样的字符串,并且该字符串必须被解释为列标识符,所以该查询的结果将使用该字符串命名的列的值。
但这不是 SQL 选择列表的工作方式。
选择列表是表达式的列表。您可以使用简单的列名,结果将是该列中的值。或者您可以使用另一个表达式,在本例中为字符串函数,结果将是该函数返回的字符串——不是恰好具有与该字符串匹配的名称的列。
正如上面评论中提到的,标识符在 SQL 查询中是固定的。您不能创建字符串表达式并将该表达式的值解释为同一查询中的标识符。要对标识符进行动态引用,您需要在准备查询之前在 SQL 语法中对其进行格式化。
你也误解了CONCAT_WS('A_', '12')
的作用。它将第二个参数和其他参数连接起来,在它们之间使用第一个参数的分隔符。一个典型的用法是:
CONCAT_WS(', ', col1, col2, col3, ...)`
这会从几个列的值中返回逗号分隔的单词列表:“value1, value2, value3”。
因此,在您的情况下,您连接了一个值“12”,但没有出现分隔符“A_”,因为列表中只有一个值。
【讨论】:
【参考方案4】:首先,你不想要CONCAT_WS()
,你想要CONCAT()
- 带有分隔符的 Concat 插入任何你的第一个参数在所有其他参数之间,并且由于你只有一个其他参数,它永远不会被使用 - 例如CONCAT_WS('A_', '12', '13')
会给你12A_13
。 CONCAT('A_', '12')
为您提供 A_12
,但作为字符串,而不是列名。
更正为 CONCAT 并进行评估后,您的选择将如下所示 SELECT id, A_12, 'A_12' as testA from TABLE_A;
请注意 A_12 周围的引号。
这是因为 concat 函数返回一个字符串,并且不能用于以您想要的方式在选择字符串中构建列名。可以这样做,但很复杂 - 您必须在字符串变量中构建整个查询字符串,然后将其作为准备好的语句执行:
SET @QueryString = CONCAT('SELECT id, A_12, ', CONCAT('A_', '12'), ' as testA from TABLE_A;');
PREPARE stmnt FROM @QueryString;
EXECUTE stmnt;
嵌套的CONCAT()
是不必要的,因为 concat 可以接受任意数量的参数,因此您可以将其简化为:
SET @QueryString = CONCAT('SELECT id, A_12, ', 'A_', '12', ' as testA from TABLE_A;');
PREPARE stmnt FROM @QueryString;
EXECUTE stmnt;
您的@QueryString 将是SELECT id, A_12, A_12 as testA from TABLE_A;
如果该字符串中的任何内容来自系统中的用户输入,这可能会非常危险。如果它连接到任何应用程序,请使用服务器端应用程序语言使用的任何连接组合字符串,然后将其作为查询执行。
DB Fiddle testing(SQLFiddle 似乎已经移除了对预处理语句中选择的支持)
【讨论】:
以上是关于MySQL 中的 SELECT 和 CONCAT的主要内容,如果未能解决你的问题,请参考以下文章