【问题标题】:Use comma delimited string from query in subquery在子查询中使用来自查询的逗号分隔字符串
【发布时间】:2014-10-22 21:20:57
【问题描述】:

我想使用逗号分隔的 ID 字符串作为同一查询的输入。

即:

Set @IDs := '';

Select @IDs := CAST(GROUP_CONCAT(DISTINCT CAST(`id` as CHAR)) AS Char) AS 'ID String',
(
 Select FORMAT(Sum(`Quantity`),0)
 from 'My Table'
 Where `ID` IN (@IDs)
 ) As 'Quantity'

From `My Table`

实际的查询要复杂得多,但我需要实现的是将逗号分隔的 ID 字符串分配给变量,并在带有 IN 子句的子查询中使用该字符串。

上述方法不起作用。如有任何反馈,我将不胜感激。

谢谢!

【问题讨论】:

  • 为什么可以将 id 转换为 int 类型而不是 chars?这对我有用。

标签: mysql variables subquery in-subquery


【解决方案1】:

MySQL 看到的是一个字符串值。它不会将该值解释为值列表,即使字符串包含逗号。

让我们通过一个例子来解释:

 SET @bar = 'fee,fi,fo,fum';
 SELECT * FROM mytable t WHERE t.foo IN (@bar) ;

相当于

 SELECT * FROM mytable t WHERE t.foo = 'fee,fi,fo,fum'

MySQL 会将@bar 视为单个值。它包含一个或多个逗号并不重要,它只是一个字符串文字;它不会被解释为 SQL 文本。这些逗号只是字符串中的字符。


解决此限制的一种方法是使用“动态 SQL”,它允许您将任意字符串作为 SQL 语句执行。您可以将所需的任何文本构造/连接到变量中,然后像执行 SQL 语句一样执行变量的内容(在 MySQL 存储过程中。您的用例将需要多个语句。但是非常 小心使用这种方法,因为这可能会导致代码受到一些恶意 SQL 注入漏洞的影响。)我不打算举例,因为我看不出你试图解决的问题保证复杂程度。


看起来问题中的查询正在尝试返回与此等效的结果:

SELECT GROUP_CONCAT(DISTINCT t.id) AS `ID String`
     , FORMAT(SUM(t.quantity),0)   AS `Quantity`
  FROM `My Table` t
 WHERE t.id IS NOT NULL

请注意,GROUP_CONCAT 函数(group_concat_max_len 变量和max_allowed_packet 变量的设置)返回的字符串长度存在限制。如果超出限制,MySQL 不会发出任何错误或警告,它会成功完成,返回一个截断到最大允许长度的字符串。

完全不清楚为什么需要子查询,或者为什么需要检查id 列的值是否是GROUP_CONCAT 函数返回的ID“列表”中包含的值之一. (也许规范中有一些我不理解的东西。)

【讨论】:

  • 谢谢斯宾塞。很详细的回答。我使用了动态 SQL,在存储过程中准备了语​​句,一切正常。查询执行从大约 9 秒下降到略低于 1。编辑 group_concat_max_len 和 max_allowed_pa​​cket 变量以防万一。至于安全性,从完全托管的 C# 代码中调用的过程,所以我不预见任何 SQL 注入的风险。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
  • 2019-10-29
  • 2012-07-20
  • 1970-01-01
  • 2017-09-09
相关资源
最近更新 更多