我有来自.net应用程序的这个字符串 A,B,C,d,E,F,
我想写一个像
这样的sql select语句set @string = 'A,B,C,D,E,F'
select * from tbl_test
where tbl_test.code in (@string)
这在t-SQL中不起作用,因为它使用@string
作为一个字符串而不是将值分开。我有什么方法可以做到这一点吗?
答案 0 :(得分:2)
3个选项
答案 1 :(得分:2)
很常见的问题!你想要的是一个表值函数。
但是不要通过写自己来重新发明轮子,我通过Google搜索sql split
找到了几十个。这是来自微软的一个:
http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=StringArrayInput
我过去常常使用动态SQL,但这意味着我必须挖掘代码并将其复制到每个新应用中。现在我甚至不用考虑它。
答案 2 :(得分:1)
动态IN子句意味着:
DECLARE @SQL NVARCHAR(4000)
SET @SQL = 'SELECT * FROM tbl_test t
WHERE t.code IN (@string_param)
BEGIN
EXEC sp_executesql @SQL N'@string_param VARCHAR(100)', @string
END
请注意sp_executesql
是2005+,并且首选,因为它会缓存查询计划。请阅读The Curse and Blessings of Dynamic SQL了解更多详情,但请注意SQL injection attacks。
答案 3 :(得分:1)
创建一个用户定义的函数,它将字符串作为输入并返回一个表:
create function [dbo].[f_SplitString] (@str as varchar (1000))
returns @t table (value varchar (50))
etc...
然后调整您的Select语句:
select * from tbl_test
where tbl_test.code in (select value from f_SplitString(@string))
答案 4 :(得分:1)
它认为最简单的方法就是动态SQL生成:
// assuming select is a SqlCommand
string[] values = "A,B,C,D,E,F".Split(',');
StringBuilder query = new StringBuilder();
query.Append("select * from tbl_test where tbl_test.code in (");
int i = 0;
foreach (string value in values) {
string paramName = "@p" + i++;
query.Append(paramName);
select.Parameters.AddWithValue(paramName, value);
}
query.Append(")");
select.CommandText = query.ToString();
// and then execute the select Command
答案 5 :(得分:1)
这是一个函数,它将分隔的String作为一组行返回
set @string = 'A,B,C,D,E,F'
select * from tbl_test
where tbl_test.code in (select r from ftDelimitedAsTable(',',@string )
--/*----------------------------------------------------------------
Create FUNCTION [dbo].[ftDelimitedAsTable](@dlm char, @string varchar(8000))
RETURNS
--------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
declare @dlm char, @string varchar(1000)
set @dlm=','; set @string='t1,t2,t3';
-- tHIS FUNCION RETUNRS IN THE ASCENDING ORDER
-- 19TH Apr 06
------------------------------------------------------------------------*/
--declare
@table_var TABLE
(id int identity(1,1),
r varchar(1000)
)
AS
BEGIN
-- a.p --
--Modified 18th Nov. 04
declare @n int,@i int
set @n=dbo.fnCountChars(@dlm,@string)+1
SET @I =1
while @I <= @N
begin
--print '@i='+convert(varchar,@i)+ ' AND INSERTING'
insert @table_var
select dbo.fsDelimitedString(@dlm,@string,@i)
set @I= @I+1
end
--PRINT '*************** ALL DONE'
if @n =1 insert @TABLE_VAR VALUES(@STRING)
--select * from @table_var
delete from @table_var where r=''
return
END
USE [QuickPickDBStaging]
GO
/****** Object: UserDefinedFunction [dbo].[fsDelimitedString] Script Date: 02/22/2010 12:31:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create function [dbo].[fsDelimitedString](
@DelimiterStr varchar(100)
,@str varchar(4000)
,@pos int=1)
returns varchar(4000)
as
/*
AP -- Dec 2003
Declare @DelimiterStr varchar(4000),@str varchar(4000) ,@pos int
set @delimiterStr = '-'
set @pos=10
set @str ='wd-1-22-333-4444-55555-666666-q-9'
*/
Begin
declare @rx varchar(4000)
set @rx=''; set @pos=@pos-1
IF DBO.fnCountChars(@DelimiterStr,@str) > 0
Begin
if dbo.fnCountChars(@delimiterStr,@str) < @pos
begin
set @rx= null
goto nulls
end
declare @i1 int,@tPos int,@ix int
set @ix=1
set @tPos=0
while @tpos <> @pos
Begin
set @ix=charindex(@DelimiterStr,@str,@ix+1)
if @ix > 0 set @tpos=@tpos+1
end
set @i1= charindex(@DelimiterStr,@str,@ix+1)
if @i1=0
set @rx=substring(@str,@ix+1,len(@str)-@ix)
else
begin
if @ix=1
set @rx=substring(@str,@ix,@i1-@ix)
else
set @rx= substring(@str, @ix+1,@i1-@ix-1)
end
-- 'print 'ix='+convert(varchar,@ix)+' @i1='+convert(varchar,@i1)+' @rx='+@rx
RETURN @RX
end
nulls:
RETURN @rx
end
答案 6 :(得分:1)
您有几种选择:
IN
语句IN
或更好的JOIN
语句(在其他实施中,我赞成SQL User Defined Function to Parse a Delimited String)。你的代码是:
select tbl_test.*
from tbl_test
inner join fn_ParseText2Table(@string) x
on tbl_test.code = x.txt_value
SQL
。答案 7 :(得分:1)
使用内置的sql函数可以保持简单:
set @string = 'A,B,C,D,E,F'
select * from tbl_test
where CHARINDEX(ISNULL(tbl_test.code, 'X'), @string) > 0
如果您需要多个角色,可以使用PATINDEX。
答案 8 :(得分:0)
没什么简单的。您可以编写一个函数,该函数将接收该列表并将其拆分为可在IN()语句中查询的表。
答案 9 :(得分:0)
我知道这是一个老问题,但无论如何我想我会回复它。我从不喜欢传入逗号分隔的字符串值,所以我过去使用过XML并在xml上使用了一个连接语句,如下所示:
declare @xml as xml
set @xml = '<v id="key1" /><v id="key2" /><v id="key3" />'
select
t.*
from
mytable t join @xml.nodes('/*') x(n)
on n.value('@id','varchar(50)') = t.mykey
答案 10 :(得分:0)
我认为,最简单的方法如下,
选项1:
set @string = '''A','B','C','D','E','F'''
Exec ('select * from tbl_test
where tbl_test.code in ('+@string+')')
选项2:
set @string = '''A','B','C','D','E','F'''
DECLARE @SQL NVARCHAR(MAX)
SET @SQL='select * from tbl_test
where tbl_test.code in ('+@string+')'
exec sp_executesql @SQL;