将逗号分隔的字符串字段拆分/分解为 SQL 查询

Blu*_*ark 5 sybase t-sql sybase-sql-anywhere string-splitting

我有场 id_list='1234,23,56,576,1231,567,122,87876,57553,1216'

我想用它来搜索IN这个领域:

SELECT * 
FROM table1
WHERE id IN (id_list)
Run Code Online (Sandbox Code Playgroud)
  • idinteger

  • id_listvarchar/text

但是这样就行不通了,所以我需要以某种方式拆分id_list为选择查询。

我应该在这里使用什么解决方案?我正在使用 T-SQL Sybase ASA 9 数据库 (SQL Anywhere)。但是这样就行不通了,所以我需要以某种方式拆分id_list为选择查询。

我看到的方式是使用while循环创建自己的函数,并根据分隔符位置搜索拆分每个元素提取,然后将元素插入到临时表中,该函数将作为结果返回。


对 Sebastian Meine 回答及其解决方案的评论:

Sybase SQL Anywhere 9

  • sa_split_list 系统程序在这里不存在,所以它不起作用

  • CAST 效果很好

Sybase SQL Anywhere 12

  • sa_split_list 系统程序存在并且运行良好

  • CAST 效果很好

对于 Sybase SQL Anywhere 9,我进行了 sa_split_list 系统过程替换:

CREATE PROCEDURE str_split_list(in str long varchar, in delim char(10) default ',')
RESULT(
  line_num integer,
  row_value long varchar)
BEGIN
  DECLARE str2 long varchar;
  DECLARE position integer;

   CREATE TABLE #str_split_list (
   line_num integer DEFAULT AUTOINCREMENT,
   row_value long varchar null,
   primary key(line_num));

   SET str = TRIM(str)+delim;
   SET position = CHARINDEX(delim, str);

   separaterows:
   WHILE position > 0 loop
       SET str2 = TRIM(LEFT(str, position - 1));
       INSERT INTO #str_split_list (row_value)
       VALUES (str2);
       SET str = RIGHT(str, LENGTH(str) - position);
       SET position = CHARINDEX(delim, str);
    end loop separaterows;

   select * from #str_split_list order by line_num asc;

END
Run Code Online (Sandbox Code Playgroud)

执行方式与 sa_split_list 相同:

select * from str_split_list('1234,23,56,576,1231,567,122,87876,57553,1216')
Run Code Online (Sandbox Code Playgroud)

Seb*_*ine 8

我实际上没有要测试的 sybase 系统,但是根据 http://dcx.sybase.com/1200/en/dbreference/sa-split-list-sysproc.html,以下解决方案应该有效:

SELECT * 
  FROM table AS T
  JOIN sa_split_list('1234,23,56,576,1231,567,122,87876,57553,1216') AS L
    ON T.id = L.row_value;
Run Code Online (Sandbox Code Playgroud)

如果 id_list 实际上存储在另一个表(比如 list_table)中,您还需要使用CROSS APPLY运算符 ( http://dcx.sybase.com/1101/en/dbusage_en11/apply-joins-joinsasp.html):

SELECT *
  FROM list_table AS LT
 CROSS APPLY sa_split_list(LT.id_list) L
  JOIN table T
    ON T.id = L.row_value
   AND <optional: some other condition that ties rows in list_table to rows in table, like a group membership or location>
Run Code Online (Sandbox Code Playgroud)

这一切都要求只有数字是这些列表的一部分,因为拆分的部分将自动转换为 id 列的数据类型。如果不是这种情况,您可以使用这种更简单但速度较慢的技术:

SELECT *
  FROM table
 WHERE ','+@id_list+',' LIKE '%,'+CAST(id AS VARCHAR(20))+',%'
Run Code Online (Sandbox Code Playgroud)

最后一个例子假设 id 列表在变量@id_list 中。如果它在另一个表中,您可以使用CROSS APPLY上面相同的技术。附加逗号确保第一个或最后一个条目可以匹配。