Динамический SQL-запрос с разделителями-запятыми - PullRequest
3 голосов
/ 05 февраля 2009

[Обновление: использование SQL Server 2005]

Привет, я хочу запросить у моей хранимой процедуры список значений (идентификаторов), разделенных запятыми, для получения строк данных.

Проблема, которую я получаю, заключается в ошибке преобразования:

Conversion failed when converting the varchar value ' +
@PassedInIDs + ' to data type int.

Утверждение в моем предложении where и ошибке:

...
AND (database.ID IN (' + @PassedInIDs + '))

Примечание: database.ID имеет тип int.

Я следил за статьей по адресу:

http://www.sql -server-helper.com / функция / разделенная запятая к table.aspx

но не завершено из-за ошибки.

В моем сценарии выполнения у меня есть:

...
@PassedInIDs= '1,5'

Я что-то здесь не так делаю? Спасибо за вашу помощь.

Ответы [ 8 ]

1 голос
/ 05 февраля 2009

Я бы создал табличную функцию CLR:

http://msdn.microsoft.com/en-us/library/ms131103.aspx

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

1 голос
/ 05 февраля 2009

Например, вы передаете строку в функцию IN в SQL. Если вы оглянетесь на исходную статью, то увидите, что вместо выполнения прямого оператора SQL вместо этого создается string, который является оператором SQL для выполнения.

1 голос
/ 05 февраля 2009

Я настоятельно рекомендую вам использовать второй метод из этой ссылки. Создайте пользовательскую функцию, которая превращает вашу строку с разделителями-запятыми в таблицу, которую вы затем можете легко выбрать.

Если вы используете Google на Erland и «Динамический SQL», у него есть хороший список подводных камней, которые он влечет за собой.

0 голосов
/ 10 июня 2015

Вот что я нашел и протестировал:

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE  FUNCTION [dbo].[SplitStrings] ( @IDsList VARCHAR(MAX) )
RETURNS @IDsTable TABLE ( [ID] VARCHAR(MAX) )
AS 
BEGIN
    DECLARE @ID VARCHAR(MAX)
    DECLARE @Pos VARCHAR(MAX)

    SET @IDsList = LTRIM(RTRIM(@IDsList)) + ','
    SET @Pos = CHARINDEX(',', @IDsList, 1)

    IF REPLACE(@IDsList, ',', '') <> '' 
        BEGIN
            WHILE @Pos > 0 
                BEGIN
                    SET @ID = LTRIM(RTRIM(LEFT(@IDsList, @Pos - 1)))
                    IF @ID <> '' 
                        BEGIN
                            INSERT  INTO @IDsTable
                                    ( [ID] )
                            VALUES  ( CAST(@ID AS VARCHAR) )
                        END
                    SET @IDsList = RIGHT(@IDsList, LEN(@IDsList) - @Pos)
                    SET @Pos = CHARINDEX(',', @IDsList, 1)
                END
        END 
    RETURN
END

GO

Вот как вызывать функцию:

SELECT * FROM dbo.SplitStrings('123,548,198,547,965')
0 голосов
/ 05 февраля 2009

это можно решить 6 способами, как указано в статье Нараяны Передача списка / массива в хранимую процедуру SQL Server

И моя самая прямолинейная реализация -

объявить @statement nvarchar (256)
set @statement = 'select * from Persons, где Persons.id в (' + @PassedInIDs + ')'
exec sp_executesql @ оператор

0 голосов
/ 05 февраля 2009

В SQL нет строковой оценки. Это:

database.ID IN (' + @PassedInIDs + ')

не будет превращено в:

database.ID IN (1,2,3)

только потому, что параметр @PassedInIDs содержит '1,2,3'. Параметр даже не просматривается, потому что все, что у вас есть, это строка , содержащая " + @PassedInIDs + ". Синтаксически это эквивалентно:

database.ID IN ('Bob')

Короче говоря, вы не можете делать то, что вы пытаетесь здесь, в SQL. Но есть еще четыре варианта:

  1. вы создаете строку SQL на языке вызова и вообще отказываетесь от хранимой процедуры
  2. вы используете динамически подготовленный оператор с таким количеством параметров в предложении IN, сколько вы собираетесь использовать
  3. вы используете фиксированный подготовленный оператор с, скажем, 10 параметрами: IN (?,?,?,?,?,?,?,?,?,?), заполняя столько, сколько вам нужно, устанавливая для других значение NULL
  4. вы создаете хранимую процедуру, скажем, с 10 параметрами и передаете столько, сколько вам нужно, устанавливая для других значение NULL: IN (@p1, @p2, ..., @p10).
0 голосов
/ 05 февраля 2009

Я предлагаю использовать XML для этого в SQL 2005. Несколько объемнее, но это может быть проще. Он позволяет вам выбрать XML в таблицу, которую затем можно соединить или вставить и т. Д.

Посмотрите на OPENXML () сервера Sql, если вы еще этого не сделали.

Например, вы можете передать что-то вроде: '12 ...

и затем используйте:

exec sp_xml_preparedocument @doc OUTPUT, @xmlParam

SELECT element 
FROM OPENXML (@doc, 'Array/Value', 2) WITH (element varchar(max) 'text()')

Это должно быть начало

0 голосов
/ 05 февраля 2009

Вам нужно обращаться с ufn_CSVToTable как с таблицей. Таким образом, вы можете присоединиться к функции:

JOIN ufn_CSVToTable(@PassedInIDs) uf ON database.ID = uf.[String]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...