web-dev-qa-db-ja.com

カンマ区切りの文字列の場所

一時テーブル#temptableの完全なリストから特定のユーザーを取得したいと思います。クエリは次のようになります。

DECLARE @List varchar(max)
SELECT @List = coalesce(@List + ',','') + '''' + StaffCode + ''''
FROM tblStaffs

SELECT UserName
FROM #temptable
WHERE #temptable.StaffCode IN (@List)

@Listが正しい形式であることがわかります。

'AAA','ABB','BBB','CCC','DDD','MMM'

そして私がそれをに変更した場合

WHERE #temptable.StaffCode IN ('AAA','ABB','BBB','CCC','DDD','MMM')

それは確かに機能します、それならなぜIN(@List)ではないのですか?

6
Weihui Guo

分割文字列関数を作成し、コンマ区切り値を行に変換すると、変換された行IN句を使用できます

DECLARE @List VARCHAR(max)

SELECT @List = COALESCE(@List + ',', '') +StaffCode
FROM   tblStaffs

SELECT UserName
FROM   #temptable
WHERE  #temptable.StaffCode IN (SELECT split_values
                                FROM   dbo.Splitstring_function(@list)) 

さまざまな分割文字列関数について here を確認してください

関数を作成したくない場合は、新しい関数を作成する代わりに、コードを直接使用することもできます(M.ALiの回答)。

別の方法は、dynamic queryを使用することです。

Declare @List varchar(max), @sql nvarchar(max)

Select @List = coalesce(@List + ',','') + '''' + StaffCode + ''''
From tblStaffs

set @sql = '
Select UserName
From #temptable
Where #temptable.StaffCode IN ('+ @List + ')'

--print @sql
exec (@sql)

動的クエリをデバッグするには、実行する前に常に動的SQLをprintします。

10

変数には、IN演算子が'AAA'',''ABB'',''BBB'として読み取る文字列があり、それを単一の値として扱うためです。

クエリでは、クエリ自体をIN演算子で次のように使用する必要があります。

Select UserName
From #temptable
Where #temptable.StaffCode IN (SELECT StaffCode From tblStaffs)

とにかく、変数を使用して、その変数からIN演算子内の値を読み取る必要がある場合は、次のようにすることができます。

DECLARE @List VARCHAR(1000);

Select @List = coalesce(@List + ',','') + StaffCode 
From tblStaffs


SELECT *
From #temptable
Where #temptable.StaffCode IN (
     SELECT t.c.value('.', 'VARCHAR(1000)')
           FROM (
                 SELECT x = CAST('<t>' + 
                  REPLACE(@List , ',', '</t><t>') + '</t>' AS XML)
                ) a
     CROSS APPLY x.nodes('/t') t(c))
5
M.Ali

カンマ区切りの文字列はまったく使用しないことをお勧めします。代わりに semi-join を検討してください。

select [Temp].[UserName] 
from 
    #temptable [Temp]
where
    exists (select 1 from [tblStaffs] where [tblStaffs].[StaffCode] = [Temp].[StaffCode]); 
2
Joe Farrell