更新 有人将此问题标记为重复 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)
id
是integer
id_list
是varchar/text
但是这样做不起作用,所以我需要以某种方式将id_list
拆分为选择查询。
我应该在这里使用什么解决方案?我正在使用T-SQL Sybase ASA 9数据库(SQL Anywhere)。
我看到这个,就是用while循环创建自己的函数, 并且每个元素提取基于分隔符位置搜索, 然后将元素插入到临时表中,该函数将返回结果。
答案 0 :(得分:4)
这可以在不使用动态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'
我希望这会有所帮助......
答案 1 :(得分:1)
您在查询中使用文本,但这不起作用。 使用动态查询。
答案 2 :(得分:1)
像 Mikael Eriksson 所说, dba.stackexchange.com 的答案有两个非常好的解决方案,首先使用sa_split_list
系统程序,使用CAST
语句慢一点。
对于Sybase SQL Anywhere 9 sa_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', ',')
答案 3 :(得分:0)
bsivel 答案的好贡献,但要概括它(对于其他分隔符而不是逗号),那么行
SET @list = LTRIM(RTRIM(@list))+ ','
必须成为
SET @list = LTRIM(RTRIM(@list))+ @delimiter
第一个版本仅适用于以逗号分隔的列表。
答案 4 :(得分:-1)
动态查询方法如下所示:
create procedure ShowData @IdList VarChar(255)
as
exec ('use yourDatabase; select * from MyTable where Id in ('+@IdList+')')