2010-09-27 5 views
1

Я пытаюсь создать следующий оператор выбора в хранимую процедурепомощи с TSQL В заявлении с ИНТОМ

@dealerids nvarchar(256) 

SELECT * 
FROM INVOICES as I 
WHERE convert(nvarchar(20), I.DealerID) in (@dealerids) 

I.DealerID является INT в таблице. и параметр для дилеров будет отформатирован, например (8820, 8891, 8834)

Когда я запускаю это с предоставленными параметрами, я не получаю никаких строк назад. Я знаю, что эти дилерские индексы должны предоставлять строки, как если бы я делал это индивидуально, я возвращаю то, что ожидаю. Я думаю, что я делаю

WHERE convert(nvarchar(20), I.DealerID) in (@dealerids) 

неправильно. Может ли кто-нибудь указать, что я здесь делаю неправильно?

ответ

2

Вы не можете использовать @dealerids подобное, вам необходимо использовать динамический SQL, например:

@dealerids nvarchar(256) 

EXEC('SELECT * 
FROM INVOICES as I 
WHERE convert(nvarchar(20), I.DealerID) in (' + @dealerids + ')' 

Недостатком является то, что вы открываете себя для атак внедрения SQL, если вы специально не контролировать данные собираются в @dealerid s.

Есть более эффективные способы обращения с этим в зависимости от вашей версии SQL Server, которые задокументированы в this great article.

+0

Огромное спасибо, я прочитаю это. Я ценю направление! – twal

2

Split @dealerids в таблицу затем РЕГИСТРИРУЙТЕСЬ

SELECT * 
FROM INVOICES as I 
JOIN 
ufnSplit(@dealerids) S ON I.DealerID = S.ParsedIntDealerID 

ассорти split functions here (я, наверное, таблица чисел в этом случае для маленькой строки

+0

Я пробовал это, он позволяет мне создать сохраненный процесс, но когда я запустил его, он выдает это искушение: Недопустимое имя объекта 'ufnSplit. к сожалению, это на SqlServer 2000 .. (я знаю, им нужно получить новую версию! :)) – twal

+0

@twal: прочитайте ссылку, напишите. или используйте ответ KM. – gbn

+0

@twal, для того, чтобы приведенный выше код работал, вам нужно создать функцию ** ufnSplit() **, которая обрабатывает строку и возвращает таблицу. Существует много ссылок, которые показывают различные способы создания этой функции. –

4

Используйте таблицу значений параметров (новый в Sql Server . 2008) Установите его, создавая фактический параметр типа таблицы:

CREATE TYPE IntTableType AS TABLE (ID INTEGER PRIMARY KEY) 

Ваша процедура будет затем:

Create Procedure up_TEST 
    @Ids IntTableType READONLY 
AS 

SELECT * 
    FROM ATable a 
    WHERE a.Id IN (SELECT ID FROM @Ids) 

RETURN 0 
GO 

Если вы не можете использовать параметры значения таблицы, см.: "Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog, тогда есть много способов разделить строку на SQL Server. В этой статье рассматриваются PRO и CON практически для каждого метода. в общем, вам нужно создать функцию split. Это как функция разделения может быть использовано:

SELECT 
    * 
    FROM YourTable        y 
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

I prefer the number table approach to split a string in TSQL но есть множество способов, чтобы разделить строки в SQL Server, см предыдущей ссылки, объясняющие плюсы и минусы каждого из них.

Для метода Числа таблицы для работы, вы должны сделать это один раз настройки таблицы, которая будет создавать таблицу Numbers, которая содержит строки от 1 до 10000:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

После того как таблица Numbers устанавливается , создать разбитую функцию:

CREATE FUNCTION [dbo].[FN_ListToTable] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
(

    ---------------- 
    --SINGLE QUERY-- --this will not return empty rows 
    ---------------- 
    SELECT 
     ListValue 
     FROM (SELECT 
        LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue 
        FROM (
          SELECT @SplitOn + @List + @SplitOn AS List2 
         ) AS dt 
         INNER JOIN Numbers n ON n.Number < LEN(dt.List2) 
        WHERE SUBSTRING(List2, number, 1) = @SplitOn 
      ) dt2 
     WHERE ListValue IS NOT NULL AND ListValue!='' 

); 
GO 

Теперь вы можете легко разделить строку CSV в таблицу и присоединиться к ней на:

Create Procedure up_TEST 
@Ids VARCHAR(MAX) 
AS 
SELECT * FROM ATable a 
WHERE a.Id IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids)) 
Смежные вопросы