1

更新: 有人将此问题标记为 How do I split a string so I can access item x 的重复项。但不同的是,我的问题是关于 Sybase SQL Anywhere,另一个是关于 MS SQL Server。这是两个不同的 SQL 引擎,即使它们的来源相同,它们的语法也不同。所以它不是重复的。我首先在描述和标签中写道,这都是关于Sybase SQL Anywhere的。

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

我想用它来搜索IN这个字段:

SELECT * 
FROM table1
WHERE id IN (id_list)
  • idinteger

  • id_listvarchar/text

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

我应该在这里使用什么解决方案?我正在使用 T-SQL Sybase ASA 9 数据库 (SQL Anywhere)。

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

4

5 回答 5

5

这可以在不使用动态 SQL 的情况下完成,但您需要创建几个支持对象。第一个对象是一个表值函数,它将解析您的字符串并返回一个整数表。第二个对象是一个存储过程,它有一个参数,您可以在其中传递字符串 (id_list),将其解析为表,然后最后将其加入查询。

首先,创建解析字符串的函数:

CREATE FUNCTION [dbo].[String_To_Int_Table]
(
         @list NVARCHAR(1024)
       , @delimiter NCHAR(1) = ',' --Defaults to CSV
)
RETURNS
    @tableList TABLE(
       value INT
       )
AS

BEGIN
   DECLARE @value NVARCHAR(11)
   DECLARE @position INT

   SET @list = LTRIM(RTRIM(@list))+ ','
   SET @position = CHARINDEX(@delimiter, @list, 1)

   IF REPLACE(@list, @delimiter, '') <> ''
   BEGIN
          WHILE @position > 0
          BEGIN 
                 SET @value = LTRIM(RTRIM(LEFT(@list, @position - 1)));
                 INSERT INTO @tableList (value)
                 VALUES (cast(@value as int));
                 SET @list = RIGHT(@list, LEN(@list) - @position);
                 SET @position = CHARINDEX(@delimiter, @list, 1);

          END
   END   
   RETURN
END

现在创建您的存储过程:

    CREATE PROCEDURE ParseListExample
    @id_list as nvarchar(1024)
    AS
    BEGIN

    SET NOCOUNT ON;

    --create a temp table to hold the list of ids
    CREATE TABLE #idTable (ID INT);

    -- use the table valued function to parse the ids into a table.
    INSERT INTO #idTable(ID)
    SELECT Value FROM   dbo.String_to_int_table(@id_list, ',');

    -- join the temp table of ids to the table you want to query...
    SELECT T1.* 
    FROM table1 T1
    JOIN #idTable T2
    on T1.ID = T2.ID

执行示例:

 exec ParseListExample @id_list='1234,23,56,576,1231,567,122,87876,57553,1216'

我希望这有帮助...

于 2013-10-12T15:34:11.913 回答
2

就像Mikael Eriksson所说,dba.stackexchange.com上有两个非常好的解决方案,第一个是使用sa_split_list系统程序,第二个是使用CAST语句较慢。

对于 Sybase SQL Anywhere 9sa_split_list系统过程不存在,所以我做了sa_split_list系统过程替换(我使用了bsivel答案的部分代码):

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

执行方式sa_split_list与默认分隔符相同,

select * from str_split_list('1234,23,56,576,1231,567,122,87876,57553,1216')

或使用可以更改的指定分隔符:

select * from str_split_list('1234,23,56,576,1231,567,122,87876,57553,1216', ',')
于 2013-12-28T16:35:02.650 回答
1

您在查询中使用文本,这是行不通的。使用动态查询。

于 2013-10-12T13:52:08.637 回答
0

bsivel答案的良好贡献,但要概括它(对于逗号以外的其他分隔符),然后是行

SET @list = LTRIM(RTRIM(@list))+ ','

必须成为

SET @list = LTRIM(RTRIM(@list))+ @delimiter

第一个版本仅适用于逗号分隔的列表。

于 2013-11-07T14:23:50.303 回答
-1

动态查询方法如下所示:

create procedure ShowData @IdList VarChar(255)
as
  exec ('use yourDatabase; select * from MyTable where Id in ('+@IdList+')')
于 2013-10-12T15:53:03.403 回答