私が次のものを得たとしましょう:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
エラー:varchar値 '、'をデータ型intに変換するときに変換に失敗しました。
エラーが発生する理由は理解していますが、解決方法がわかりません...
次のような動的なspとしてこれを実行する必要があります
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = '3,4,22,6014'
declare @sql nvarchar(Max)
Set @sql='SELECT * FROM [A] WHERE Id NOT IN ('+@ExcludedList+')'
exec sp_executesql @sql
これは、テーブル変数を使用してIN句の複数の値をリストする例です。明らかな理由は、長い手順で値のリストを1箇所のみ変更できることです。
さらに動的でユーザー入力を少なくするために、入力にvarchar変数を宣言し、WHILEを使用して変数内のデータをループしてテーブル変数に挿入することをお勧めします。
@ your_list、Your_table、および値を実際のものに置き換えます。
DECLARE @your_list TABLE (list varchar(25))
INSERT into @your_list
VALUES ('value1'),('value2376')
SELECT *
FROM your_table
WHERE your_column in ( select list from @your_list )
Select文aboweは次と同じことを行います。
SELECT *
FROM your_table
WHERE your_column in ('value','value2376' )
DECLARE @IDQuery VARCHAR(MAX)
SET @IDQuery = 'SELECT ID FROM SomeTable WHERE Condition=Something'
DECLARE @ExcludedList TABLE(ID VARCHAR(MAX))
INSERT INTO @ExcludedList EXEC(@IDQuery)
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
古い投稿に応答していることは知っていますが、動的SQLの使用を避けたい場合に変数テーブルを使用する方法の例を共有したいと思いました。最も効率的な方法かどうかはわかりませんが、これは過去に動的SQLがオプションではなかったときに機能していました。
IN
句で変数を使用することはできません- 動的SQL を使用するか、または 関数(TSQLまたはCLR)を使用して値のリストを変換する必要がありますテーブルに 。
動的SQLの例:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ',' + 4 + ',' + '22'
DECLARE @SQL NVARCHAR(4000)
SET @SQL = 'SELECT * FROM A WHERE Id NOT IN (@ExcludedList) '
BEGIN
EXEC sp_executesql @SQL '@ExcludedList VARCHAR(MAX)' @ExcludedList
END
最初に、次のように、値の区切りリストをテーブルに分割するクイック関数を作成します。
CREATE FUNCTION dbo.udf_SplitVariable
(
@List varchar(8000),
@SplitOn varchar(5) = ','
)
RETURNS @RtnValue TABLE
(
Id INT IDENTITY(1,1),
Value VARCHAR(8000)
)
AS
BEGIN
--Account for ticks
SET @List = (REPLACE(@List, '''', ''))
--Account for 'emptynull'
IF LTRIM(RTRIM(@List)) = 'emptynull'
BEGIN
SET @List = ''
END
--Loop through all of the items in the string and add records for each item
WHILE (CHARINDEX(@SplitOn,@List)>0)
BEGIN
INSERT INTO @RtnValue (value)
SELECT Value = LTRIM(RTRIM(SUBSTRING(@List, 1, CHARINDEX(@SplitOn, @List)-1)))
SET @List = SUBSTRING(@List, CHARINDEX(@SplitOn,@List) + LEN(@SplitOn), LEN(@List))
END
INSERT INTO @RtnValue (Value)
SELECT Value = LTRIM(RTRIM(@List))
RETURN
END
次に、このような関数を呼び出します...
SELECT *
FROM A
LEFT OUTER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value
WHERE f.Id IS NULL
これは私たちのプロジェクトで本当にうまくいきました...
もちろん、もしそうであれば、あなたの質問ではありませんが、反対も行うことができます。
SELECT *
FROM A
INNER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value
これは、オプションの複数選択パラメーターリストを持つレポートを処理する際に非常に便利です。パラメーターがNULLの場合、すべての値を選択する必要がありますが、1つ以上の値がある場合は、それらの値でレポートデータをフィルター処理します。次に、次のようにSQLを使用します。
SELECT *
FROM A
INNER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value OR @ExcludeList IS NULL
このように、@ ExcludeListがNULL値の場合、結合のOR句は、この値のフィルタリングをオフにするスイッチになります。非常に便利です...
問題があると思う
3 + ', ' + 4
に変更する
'3' + ', ' + '4'
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = '3' + ', ' + '4' + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
クエリが次のようになるように@ExcludedListeを設定します
いずれか
SELECT * FROM A WHERE Id NOT IN ('3', '4', '22')
または
SELECT * FROM A WHERE Id NOT IN (3, 4, 22)
動的クエリなしでそれを行う別のソリューションがあります。同様にxqueryを使用して行うことができます。
SET @Xml = cast(('<A>'+replace('3,4,22,6014',',' ,'</A><A>')+'</A>') AS XML)
Select @Xml
SELECT A.value('.', 'varchar(max)') as [Column] FROM @Xml.nodes('A') AS FN(A)
完全なソリューションは次のとおりです: http://raresql.com/2011/12/21/how-to-use-multiple-values-for-in-clause-using-same-parameter -sql-server /
これを試して:
CREATE PROCEDURE MyProc @excludedlist integer_list_tbltype READONLY AS
SELECT * FROM A WHERE ID NOT IN (@excludedlist)
そして、次のように呼び出します:
DECLARE @ExcludedList integer_list_tbltype
INSERT @ExcludedList(n) VALUES(3, 4, 22)
exec MyProc @ExcludedList