Saya memiliki kueri Transact-SQL yang menggunakan operator IN. Sesuatu seperti ini:
select * from myTable where myColumn in (1,2,3,4)
Apakah ada cara untuk mendefinisikan variabel untuk menampung seluruh daftar "(1,2,3,4)"? Bagaimana saya harus mendefinisikannya?
declare @myList {data type}
set @myList = (1,2,3,4)
select * from myTable where myColumn in @myList
Jawaban:
DECLARE @MyList TABLE (Value INT) INSERT INTO @MyList VALUES (1) INSERT INTO @MyList VALUES (2) INSERT INTO @MyList VALUES (3) INSERT INTO @MyList VALUES (4) SELECT * FROM MyTable WHERE MyColumn IN (SELECT Value FROM @MyList)
sumber
DECLARE @mylist TABLE (Id int) INSERT INTO @mylist SELECT id FROM (VALUES (1),(2),(3),(4),(5)) AS tbl(id) SELECT * FROM Mytable WHERE theColumn IN (select id from @mylist)
sumber
[Err] 42000 - [SQL Server]Must declare the scalar variable "@mylist".
(VALUES (1),(2),(3),(4),(5))
langsung menggunakan ?Ada dua cara untuk menangani daftar csv dinamis untuk kueri TSQL:
1) Menggunakan seleksi dalam
SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
2) Menggunakan TSQL yang digabungkan secara dinamis
DECLARE @sql varchar(max) declare @list varchar(256) select @list = '1,2,3' SELECT @sql = 'SELECT * FROM myTable WHERE myColumn in (' + @list + ')' exec sp_executeSQL @sql
3) Kemungkinan opsi ketiga adalah variabel tabel. Jika Anda memiliki SQl Server 2005 Anda dapat menggunakan variabel tabel. Jika Anda di Sql Server 2008, Anda bahkan dapat mengirimkan seluruh variabel tabel sebagai parameter untuk prosedur yang tersimpan dan menggunakannya dalam gabungan atau sebagai subpilih dalam klausa IN.
DECLARE @list TABLE (Id INT) INSERT INTO @list(Id) SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 SELECT * FROM myTable JOIN @list l ON myTable.myColumn = l.Id SELECT * FROM myTable WHERE myColumn IN (SELECT Id FROM @list)
sumber
Gunakan fungsi seperti ini:
CREATE function [dbo].[list_to_table] (@list varchar(4000)) returns @tab table (item varchar(100)) begin if CHARINDEX(',',@list) = 0 or CHARINDEX(',',@list) is null begin insert into @tab (item) values (@list); return; end declare @c_pos int; declare @n_pos int; declare @l_pos int; set @c_pos = 0; set @n_pos = CHARINDEX(',',@list,@c_pos); while @n_pos > 0 begin insert into @tab (item) values (SUBSTRING(@list,@c_pos+1,@n_pos - @c_pos-1)); set @c_pos = @n_pos; set @l_pos = @n_pos; set @n_pos = CHARINDEX(',',@list,@c_pos+1); end; insert into @tab (item) values (SUBSTRING(@list,@l_pos+1,4000)); return; end;
Alih-alih menggunakan like, Anda membuat gabungan dalam dengan tabel yang dikembalikan oleh fungsi:
select * from table_1 where id in ('a','b','c')
menjadi
select * from table_1 a inner join [dbo].[list_to_table] ('a,b,c') b on (a.id = b.item)
Dalam tabel catatan 1 juta yang tidak diindeks, versi kedua membutuhkan waktu sekitar separuh waktu ...
Bersulang
sumber
DECLARE @myList TABLE (Id BIGINT) INSERT INTO @myList(Id) VALUES (1),(2),(3),(4); select * from myTable where myColumn in(select Id from @myList)
Harap dicatat bahwa untuk daftar panjang atau sistem produksi tidak disarankan menggunakan cara ini karena mungkin jauh lebih lambat daripada
IN
operator sederhana sepertisomeColumnName in (1,2,3,4)
(diuji menggunakan 8000+ daftar item)sumber
Tidak, tidak ada tipe seperti itu. Tetapi ada beberapa pilihan:
Tak satu pun dari ini benar-benar elegan, tapi itulah yang terbaik.
sumber
sedikit perbaikan pada @LukeH, tidak perlu mengulang "INSERT INTO": dan jawaban @ realPT - tidak perlu memiliki SELECT:
DECLARE @MyList TABLE (Value INT) INSERT INTO @MyList VALUES (1),(2),(3),(4) SELECT * FROM MyTable WHERE MyColumn IN (SELECT Value FROM @MyList)
sumber
Saya tahu ini sudah tua sekarang tetapi TSQL => 2016, Anda dapat menggunakan STRING_SPLIT:
DECLARE @InList varchar(255) = 'This;Is;My;List'; WITH InList (Item) AS ( SELECT value FROM STRING_SPLIT(@InList, ';') ) SELECT * FROM [Table] WHERE [Item] IN (SELECT Tag FROM InList)
sumber
Dimulai dengan SQL2017, Anda dapat menggunakan STRING_SPLIT dan melakukan ini:
declare @myList nvarchar(MAX) set @myList = '1,2,3,4' select * from myTable where myColumn in (select value from STRING_SPLIT(@myList,','))
sumber
Jika Anda ingin melakukan ini tanpa menggunakan tabel kedua, Anda dapat melakukan perbandingan LIKE dengan CAST:
DECLARE @myList varchar(15) SET @myList = ',1,2,3,4,' SELECT * FROM myTable WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
Jika bidang yang Anda bandingkan sudah berupa string, Anda tidak perlu melakukan CAST.
Mengitari kecocokan kolom dan setiap nilai unik dalam koma akan memastikan kecocokan persis. Jika tidak, nilai 1 akan ditemukan dalam daftar yang berisi ', 4,2,15,'
sumber
Karena tidak ada yang menyebutkannya sebelumnya, mulai dari Sql Server 2016 Anda juga dapat menggunakan json array dan
OPENJSON (Transact-SQL)
:declare @filter nvarchar(max) = '[1,2]' select * from dbo.Test as t where exists (select * from openjson(@filter) as tt where tt.[value] = t.id)
Anda dapat mengujinya di sql fiddle demo
Anda juga dapat mencakup kasus yang lebih rumit dengan json lebih mudah - lihat Cari daftar nilai dan rentang dalam SQL menggunakan klausa WHERE IN dengan variabel SQL?
sumber
Yang ini menggunakan PATINDEX untuk mencocokkan id dari tabel ke daftar bilangan bulat yang dipisahkan bukan digit.
-- Given a string @myList containing character delimited integers -- (supports any non digit delimiter) DECLARE @myList VARCHAR(MAX) = '1,2,3,4,42' SELECT * FROM [MyTable] WHERE -- When the Id is at the leftmost position -- (nothing to its left and anything to its right after a non digit char) PATINDEX(CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0 OR -- When the Id is at the rightmost position -- (anything to its left before a non digit char and nothing to its right) PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR), @myList)>0 OR -- When the Id is between two delimiters -- (anything to its left and right after two non digit chars) PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0 OR -- When the Id is equal to the list -- (if there is only one Id in the list) CAST([Id] AS VARCHAR)=@myList
Catatan:
sumber
DECLARE @StatusList varchar(MAX); SET @StatusList='1,2,3,4'; DECLARE @Status SYS_INTEGERS; INSERT INTO @Status SELECT Value FROM dbo.SYS_SPLITTOINTEGERS_FN(@StatusList, ','); SELECT Value From @Status;
sumber
Saya pikir Anda harus mendeklarasikan string dan kemudian mengeksekusi string SQL itu.
Lihat sp_executeSQL
sumber