私が次のものを持っているとしましょう:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
エラー : varchar 値 ', ' をデータ型 int に変換するときに変換に失敗しました。
エラーの原因はわかったのですが、解決方法がわかりません...
私が次のものを持っているとしましょう:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
エラー : varchar 値 ', ' をデータ型 int に変換するときに変換に失敗しました。
エラーの原因はわかったのですが、解決方法がわかりません...
これは、テーブル変数を使用して 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 ステートメントは、次と同じことを行います。
SELECT *
FROM your_table
WHERE your_column in ('value','value2376' )
これを動的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
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)
クエリが次のようになるように SET @ExcludedListe
また
SELECT * FROM A WHERE Id NOT IN ('3', '4', '22')
また
SELECT * FROM A WHERE Id NOT IN (3, 4, 22)
これを試して:
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
動的クエリなしでそれを行う別の解決策があります。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)
完全な解決策は次のとおりです 。