2010-12-18 78 views
2

我在IN SQL语句有一个小问题。我只是想知道有人能帮助我吗?TSQL声明IN

@Ids = "1,2,3,4,5" 

SELECT * FROM Nav WHERE CONVERT(VARCHAR,NavigationID) IN (CONVERT(VARCHAR,@Ids)) 

这回来了,下面的错误,我相信这很简单!

Conversion failed when converting the varchar value '1,' to data type int. 

回答

4

SQL IN子句不接受单个变量来表示值列表 - 没有使用动态SQL,数据库没有。否则,可以使用use a Table Valued Function(SQL Server 2000+)将值从列表中提取出来。&将它们返回为您可以加入的表。

动态SQL例如:

EXEC('SELECT * 
     FROM Nav 
     WHERE NavigationID IN ('+ @Ids +')') 

我建议使用SQL Server上的动态SQL之前阅读The curse and blessings of dynamic SQL

+0

作为一个侧面说明,动态查询不能很好地处理查询优化器,但这不是问题。 – 2010-12-18 20:39:14

+1

@PulsarBlow:“处理得好”是模糊的,而且不正确 - 动态和非动态查询与优化器没有区别。但是'EXEC'已知不会缓存查询计划,而'sp_executesql'确实不会。我建议你阅读关于动态sql的诅咒和祝福的链接。 – 2010-12-18 20:44:21

0

您正在做的事情对于SQL IN语句不可行。您无法将字符串传递给它,并期望该字符串被解析。 IN用于特定的硬编码值。

1

杰森:

首先创建这样

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 
    declare @n int,@i int 
    set @n=dbo.fnCountChars(@dlm,@string)+1 
    SET @I =1 
    while @I <= @N 
     begin 
      insert @table_var 
       select dbo.fsDelimitedString(@dlm,@string,@i) 
      set @I= @I+1 

     end 
    if @n =1 insert @TABLE_VAR VALUES(@STRING) 
    delete from @table_var where r='' 
    return 
END 

一个函数,然后

set quoted_identifier off 
declare @ids varchar(max) 
select @Ids = "1,2,3,4,5" 
declare @nav table (navigationid int identity(1,1),theother bigint) 
insert @nav(theother) select 10 union select 11 union select 15 
SELECT * FROM @Nav WHERE CONVERT(VARCHAR,NavigationID) IN (select id from dbo.ftDelimitedAsTable(',',@Ids)) 

select * from dbo.ftDelimitedAsTable(',',@Ids) 
+0

+1:对于表值函数示例 – 2010-12-18 20:47:07

0

有两种方法可以做到你想在这里做什么。 一个是创建一个'动态sql'查询并执行它,代入IN列表后。

DECLARE @query varchar(max); 
SET @query = 'SELECT * FROM Nav WHERE CONVERT(VARCHAR,NavigationID) IN (' + @Ids + ')' 
exec (@query) 

这会产生性能影响和其他并发症。通常我会尽量避免它。

另一种方法是使用用户定义函数(UDF)将字符串拆分为其组成部分,然后对其进行查询。 有一个帖子详细介绍了如何一旦函数存在创建功能here

,是微不足道的加入到它

SELECT * FROM Nav 
CROSS APPLY dbo.StringSplit(@Ids) a 
WHERE a.s = CONVERT(varchar, Nav.NavigationId) 

NB-的“作为”字段引用基于链接的功能,哪些商店名为's'的列中的拆分值。这可能会因您的字符串分割函数的实现而有所不同

这很好,因为它使用基于集合的方法查询而不是IN子查询,但CROSS JOIN可能有点复杂,所以如果你想保持IN语法,那么下面的应该工作:

SELECT * FROM Nav 
WHERE Nav.NavigationId IN 
    (SELECT CONVERT(int, a.s) AS Value 
    FROM dbo.StringSplit(@Ids) a