IN অপারেটর (টি-এসকিউএল) এর সাথে ব্যবহারের জন্য ভেরিয়েবলের সংজ্ঞা দিন


138

আমার কাছে একটি লেনদেন-এসকিউএল কোয়েরি রয়েছে যা IN অপারেটরটি ব্যবহার করে। এটার মতো কিছু:

select * from myTable where myColumn in (1,2,3,4)

পুরো তালিকা "(1,2,3,4)" ধরে রাখার জন্য কোনও ভেরিয়েবলকে সংজ্ঞায়িত করার কোনও উপায় আছে কি? আমি এটি কীভাবে সংজ্ঞায়িত করব?

declare @myList {data type}
set @myList = (1,2,3,4)
select * from myTable where myColumn in @myList

7
এই প্রশ্নটি "প্যারামিটারাইজ এ এসকিউএল ইন ক্লজ" প্রশ্নের মতো নয়। এই প্রশ্নটি দেশীয় টি-এসকিউএলকে বোঝায়, অন্য প্রশ্নটি সি # কে বোঝায়।
স্লগমিস্টার এক্সট্রাওর্ডিনায়ার

উত্তর:


113
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)

47
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)

টি-এসকিউএল বলেছেন[Err] 42000 - [SQL Server]Must declare the scalar variable "@mylist".
সিস টিমারম্যান

1
আপনার জন্য এটি ঠিক করেছেন @ পল
স্টিফান জেড ক্যামিলারি

5
আপনি কি (VALUES (1),(2),(3),(4),(5))সরাসরি ব্যবহার করতে পারবেন ?
টুডমো

এটি আমার প্রয়োজনের জন্য সেরা সমাধান ছিল। আইডিগুলির তালিকা হিসাবে আমার একটি ভেরিয়েবলের প্রয়োজন ছিল যা আমি একটি নির্বাচন থেকে পেয়ে যাচ্ছিলাম যাতে মানগুলি পূর্বনির্ধারিত না হয়। এটি আমার যা প্রয়োজন ঠিক তা সম্পাদন করেছে। ধন্যবাদ!
Lexi847942

12

টিএসকিউএল কোয়েরিগুলির জন্য ডায়নামিক সিএসভি তালিকাগুলি মোকাবেলার জন্য দুটি উপায় রয়েছে:

1) একটি অভ্যন্তরীণ নির্বাচন ব্যবহার

SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)

2) গতিশীলভাবে সংঘবদ্ধ টিএসকিউএল ব্যবহার করা

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) একটি সম্ভাব্য তৃতীয় বিকল্প হ'ল টেবিল ভেরিয়েবল। আপনার যদি এসকিউএল সার্ভার 2005 থাকে তবে আপনি একটি সারণী ভেরিয়েবল ব্যবহার করতে পারেন। আপনার যদি এসকিএল সার্ভার ২০০৮ তে থাকে আপনি এমনকি পুরো টেবিলের ভেরিয়েবলগুলিকে সঞ্চিত পদ্ধতিতে প্যারামিটার হিসাবে পাস করতে পারেন এবং এটিকে একটি জোনে বা আইএন ক্লজে সাব-সাবলেট হিসাবে ব্যবহার করতে পারেন।

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)

5
@ ব্যাডবড৯৯ - সাধারণীকরণের কথা এবং সমস্ত সাধারণীকরণ ভুল হয় :) আমি বিকল্প প্রস্তাব দিয়েছি
হলি স্টাইলগুলি

1
@ ভিলাক্স - আপনার পরিবর্তনশীল @ তালিকা নির্ধারণের অর্থ কি? যদি সেটটি ঠিক থাকে তবে কেবল একটি ভেরিয়েবল সেট করে, নির্বাচন করে আপনি একটি স্টেটমেন্টে বেশ কয়েকটি ভেরিয়েবল পপুলেট করতে পারেন। তাদের মধ্যে তেমন কিছু না থাকায় আমি সর্বদা নির্বাচন নির্বাচন করার অভ্যাসে আছি।
হলি স্টাইলগুলি

1
সত্য ... খুব সাধারণ আপনার বিকল্প আরও ভাল। আমার সত্যিকার অর্থে একটি এসকিউএল স্ক্রিপ্টের মধ্যে থেকে এসকিউএল উত্পন্ন করার ফলে সাধারণত অভাবনীয় কোড, ইনজেকশন আক্রমণগুলির ঝুঁকি এবং অন্যান্য ঘৃণ্যতার কারণ হয়।
Badbod99

9

এর মতো একটি ফাংশন ব্যবহার করুন:

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;

পছন্দটি ব্যবহার না করে আপনি ফাংশনটি দিয়ে ফিরে আসা টেবিলের সাথে একটি অভ্যন্তরীণ যোগ দিন:

select * from table_1 where id in ('a','b','c')

হয়ে

select * from table_1 a inner join [dbo].[list_to_table] ('a,b,c') b on (a.id = b.item)

অনিবন্ধিত 1 এম রেকর্ড সারণীতে দ্বিতীয় সংস্করণটি প্রায় অর্ধেক সময় নিয়েছিল ...

চিয়ার্স


5
DECLARE @myList TABLE (Id BIGINT) INSERT INTO @myList(Id) VALUES (1),(2),(3),(4);
select * from myTable where myColumn in(select Id from @myList)

দয়া করে নোট করুন যে দীর্ঘ তালিকা বা উত্পাদন সিস্টেমের জন্য এটি এ জাতীয়ভাবে ব্যবহার করার পরামর্শ দেওয়া হয়নি কারণ এটি সাধারণ INঅপারেটরের তুলনায় অনেক ধীর হতে পারে someColumnName in (1,2,3,4)(8000+ আইটেমের তালিকা ব্যবহার করে পরীক্ষিত)


4

না, এরকম কোনও ধরণের নেই। তবে কিছু পছন্দ আছে:

  • গতিশীলভাবে উত্পন্ন উত্সগুলি (sp_executesql)
  • অস্থায়ী টেবিলগুলি
  • সারণী-ধরণের ভেরিয়েবল (নিকটে থাকা জিনিস যা তালিকার সাথে রয়েছে)
  • একটি এক্সএমএল স্ট্রিং তৈরি করুন এবং তারপরে এটি এক্সএমএল ফাংশনগুলির সাথে একটি টেবিলে রূপান্তর করুন (সত্যিই বিশ্রী এবং চক্রাকারে, যদি আপনার সাথে শুরু করার জন্য কোনও এক্সএমএল না থাকে)

এগুলির কোনওই সত্যিই মার্জিত নয়, তবে এটি সর্বোত্তম।


4

@ লুক এ সামান্য উন্নতি, "INSERT INTO": এবং @ রিয়েলপিটির উত্তরটি পুনরাবৃত্তি করার প্রয়োজন নেই - নির্বাচন করার দরকার নেই:

DECLARE @MyList TABLE (Value INT) 
INSERT INTO @MyList VALUES (1),(2),(3),(4)

SELECT * FROM MyTable
WHERE MyColumn IN (SELECT Value FROM @MyList)

4

আমি জানি এটি এখন পুরানো তবে টিএসকিউএল => 2016, আপনি 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)

4

SQL2017 থেকে শুরু করে আপনি ব্যবহার করতে পারেন STRING_SPLIT এবং এই একটি করুন:

declare @myList nvarchar(MAX)
set @myList = '1,2,3,4'
select * from myTable where myColumn in (select value from STRING_SPLIT(@myList,','))

2

আপনি যদি দ্বিতীয় টেবিলটি ব্যবহার না করে এটি করতে চান তবে আপনি কাস্টের সাথে একটি তুলনা পছন্দ করতে পারেন:

DECLARE @myList varchar(15)
SET @myList = ',1,2,3,4,'

SELECT *
FROM myTable
WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'

আপনি যে ক্ষেত্রটির সাথে তুলনা করছেন তা যদি ইতিমধ্যে একটি স্ট্রিং হয় তবে আপনাকে কাস্ট করার প্রয়োজন হবে না।

কলামের ম্যাচ এবং কমাতে প্রতিটি অনন্য মান উভয়কে ঘিরে একটি সঠিক মিল নিশ্চিত করবে। অন্যথায়, ', 4,2,15,' সমন্বিত তালিকায় 1 টির মান পাওয়া যাবে


1

যেমনটি এর আগে কেউ উল্লেখ করেনি, স্কেল সার্ভার 2016 থেকে শুরু করে আপনি জসন অ্যারে এবং ব্যবহার করতে পারেন 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)

আপনি এটি পরীক্ষা করতে পারেন sql fiddle demo

আপনি আরও জটিল কেসনগুলি সহজভাবে জসন সহ কভার করতে পারেন - এসকিউএল ভেরিয়েবলের সাথে ক্লোজ ইন ক্লাউজ ব্যবহার করে এসকিউএলে মান এবং ব্যাপ্তির অনুসন্ধানের তালিকাটি দেখুন ?


1

এই একটি একটি টেবিল থেকে অ-অঙ্কের সীমানাঙ্কিত পূর্ণসংখ্যার তালিকায় আইডির সাথে মেলে PATINDEX ব্যবহার করে।

-- 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

মন্তব্য:

  • যখন বারচার হিসাবে কাস্টিং করা হয় এবং বন্ধনীগুলিতে বাইট আকার নির্দিষ্ট না করে ডিফল্ট দৈর্ঘ্য 30 হয়
  • % (ওয়াইল্ডকার্ড) শূন্য বা আরও বেশি অক্ষরের যে কোনও স্ট্রিংয়ের সাথে মিলবে
  • ^ (ওয়াইল্ডকার্ড) মেলে না
  • [^ 0-9] কোনও অ-অঙ্কের অক্ষরের সাথে মিলবে
  • প্যাটিনডেক্স একটি এসকিউএল স্ট্যান্ডার্ড ফাংশন যা স্ট্রিংয়ে একটি প্যাটার্নের অবস্থানটি দেয়

0
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;

5
আপনি যদি নিজের কোডটি সেখানে বর্ণনা করেন তবে এটি আরও ভাল উত্তর হতে পারে!
দীপ কাক্কার

0

আমি মনে করি আপনাকে একটি স্ট্রিং ঘোষণা করতে হবে এবং তারপরে সেই এসকিউএল স্ট্রিং কার্যকর করতে হবে।

Sp_executeSQL এ দেখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.