TSQL Statement IN - PullRequest
       2

TSQL Statement IN

2 голосов
/ 18 декабря 2010

У меня небольшая проблема с оператором IN SQL.Мне просто интересно, может ли кто-нибудь помочь мне?

@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 ]

4 голосов
/ 18 декабря 2010

Предложение SQL IN не принимает единственную переменную для представления списка значений - ни одна база данных не может обойтись без использования динамического SQL.В противном случае вы могли бы использовать табличную функцию (SQL Server 2000+), чтобы извлечь значения из списка и вернуть их в виде таблицы, к которой вы можете присоединиться.

Пример динамического SQL:

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

Я рекомендую прочитать Проклятие и благословения динамического SQL перед использованием динамического SQL на SQL Server.

1 голос
/ 18 декабря 2010

Джейсон:

Сначала создайте функцию, подобную этой

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 голосов
/ 04 января 2011

Есть два способа сделать то, что вы хотите сделать здесь.Один из них - создать динамический SQL-запрос и выполнить его после замены в списке IN.

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

Это может повлиять на производительность и привести к другим сложностям.Обычно я стараюсь избегать этого.

Другой метод заключается в использовании пользовательской функции (UDF), чтобы разбить строку на составные части и затем выполнить запрос.Здесь есть сообщение о том, как создать эту функцию здесь

Как только функция существует, присоединиться к ней тривиально

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

NB - ссылка на поле 'as'основан на связанной функции, которая хранит значение разделения в столбце с именем 's'.Это может отличаться в зависимости от реализации вашей функции разделения строк

Это хорошо, потому что он использует подход на основе множеств к запросу, а не подзапрос IN, но CROSS JOIN может быть немного сложным на данный момент,поэтому, если вы хотите сохранить синтаксис IN, должно работать следующее:

SELECT * FROM Nav
WHERE Nav.NavigationId IN
    (SELECT CONVERT(int, a.s) AS Value
    FROM dbo.StringSplit(@Ids) a
0 голосов
/ 18 декабря 2010

То, что вы делаете, невозможно с оператором SQL IN.Вы не можете передать ему строку и ожидать, что эта строка будет проанализирована.IN предназначен для конкретных жестко закодированных значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...