পূর্ণসংখ্যার তালিকা ধরে রাখতে এসকিউএল পরিবর্তনশীল


175

আমি অন্য কারোর এসকিউএল রিপোর্টগুলি ডিবাগ করার চেষ্টা করছি এবং এসকিউএল ২০১২ এর কোয়েরি উইন্ডোতে অন্তর্নিহিত প্রতিবেদনের ক্যোয়ারী রেখেছি।

প্রতিবেদনের জন্য যে পরামিতিগুলির জন্য অনুরোধ করা হয়েছে তার মধ্যে একটি হল পূর্ণসংখ্যার একটি তালিকা। এটি বহু-নির্বাচন ড্রপ ডাউন বাক্সের মাধ্যমে রিপোর্টে অর্জন করা হয়েছে। প্রতিবেদনের অন্তর্নিহিত ক্যোয়ারী whereক্লজ যেমন এই পূর্ণসংখ্যা তালিকাটি ব্যবহার করে

select *
from TabA
where TabA.ID in (@listOfIDs)

আমি ডিবাগ করছি এমন ক্যোয়ারীটি সংশোধন করতে চাই না তবে এসকিউএল সার্ভারে কীভাবে এই ভেরিয়েবল তৈরি করতে হয় তা পরীক্ষা করতে এই ধরণের ডেটা ধরে রাখতে পারি তা বুঝতে পারি না।

যেমন

declare @listOfIDs int
set listOfIDs  = 1,2,3,4

কোনও ডেটাটাইপ নেই যা পূর্ণসংখ্যার একটি তালিকা ধরে রাখতে পারে, তাই আমি কীভাবে প্রতিবেদনটির একই মানগুলির সাথে আমার এসকিউএল সার্ভারে রিপোর্ট ক্যোয়ারী চালাতে পারি?


1
আমি জানি আমি ডেটা toোকানোর জন্য টিভিপি টেবিল মান প্যারামিটার ব্যবহার করেছি তবে এখন নিশ্চিত যে এটি কোনও জায়গায় ব্যবহার করা যায় কিনা। পরিণাম?
পাপারাজ্জো

2
ভাল শব্দযুক্ত প্রশ্ন। +1
RayLoveless

উত্তর:


224

টেবিল পরিবর্তনশীল

declare @listOfIDs table (id int);
insert @listOfIDs(id) values(1),(2),(3);    

select *
from TabA
where TabA.ID in (select id from @listOfIDs)

অথবা

declare @listOfIDs varchar(1000);
SET @listOfIDs = ',1,2,3,'; --in this solution need put coma on begin and end

select *
from TabA
where charindex(',' + CAST(TabA.ID as nvarchar(20)) + ',', @listOfIDs) > 0

2
তার জন্য ধন্যবাদ তবে আবার এটির জন্য আমাকে জিজ্ঞাসায় যেভাবে চলকটি পড়তে হবে তা আবার লিখতে হবে। আমি এটা একই রাখা আছে।
এরিকট্রিপটপস

3
আপনি যদি না জানেন যে আইডিগুলি কী এবং সেগুলি কোয়েরি থেকে আসে? উদাহরণ: SET @AddressIDs = (SELECT ID FROM address WHERE Account = 1234)এই ক্যোয়ারীটি একাধিক আইডি ফেরত দেবে এবং আমি এই বলে একটি ত্রুটি পেয়েছি যে সাবকুইটি একাধিক ফলাফল প্রত্যাবর্তন করেছে এবং এটি অনুমোদিত নয়। কোনও উপকরণ থেকে আইডি যদি একটি অ্যারে সঞ্চয় করে যে কোনও ভেরিয়েবল তৈরি করার কি আছে?
রাফায়েল

1
আমি দ্বিতীয় বিকল্পটি চেষ্টা করেছিলাম এবং এটি কম সংখ্যক রেকর্ডের জন্য কাজ করে। আমি যখন আইডির সংখ্যা বাড়িয়ে দিই তখন আমি টাইমআউট ত্রুটি পাই। সম্ভবত কাস্ট অভিনয়টি বাধাগ্রস্থ করছে।
ব্যবহারকারী এম

মূল প্রশ্নের উত্তর নয় তবে এটি আমি জিজ্ঞাসা করি না এমন উত্তর, তাই আমি ভাল। আমি একটি প্যারামিটার হিসাবে <int> তালিকায় পাস করি তবে এসএসএমএসে পরীক্ষার জন্য স্থানীয় পরিবর্তনশীল করতে চাই। এটি হত্যাকারী
ওয়েড হ্যাটার 18

দুর্দান্ত উত্তর, আমাকে অনেক সময় সাশ্রয় করেছে
আলফ্রেডো এ।

35

ভেরিয়েবল ধরে নেওয়া এইরকম কিছু:

CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [int] NOT NULL
)

এবং সঞ্চিত পদ্ধতিটি এই ফর্মটিতে এটি ব্যবহার করছে:

ALTER Procedure [dbo].[GetFooByIds]
    @Ids [IntList] ReadOnly
As 

আপনি ইন্টলিস্ট তৈরি করতে পারেন এবং পদ্ধতিটি কল করতে পারেন:

Declare @IDs IntList;
Insert Into @IDs Select Id From dbo.{TableThatHasIds}
Where Id In (111, 222, 333, 444)
Exec [dbo].[GetFooByIds] @IDs

অথবা আপনি যদি নিজেই ইন্টারলিস্ট সরবরাহ করছেন

DECLARE @listOfIDs dbo.IntList
INSERT INTO @listofIDs VALUES (1),(35),(118);

17

আপনি ঠিক বলেছেন, এসকিউএল-সার্ভারে কোনও ডেটাটাইপ নেই যা পূর্ণসংখ্যার একটি তালিকা রাখতে পারে। তবে আপনি যা করতে পারেন তা হল স্ট্রিং হিসাবে পূর্ণসংখ্যার একটি তালিকা।

DECLARE @listOfIDs varchar(8000);
SET @listOfIDs = '1,2,3,4';

তারপরে আপনি স্ট্রিংটিকে পৃথক পূর্ণসংখ্যার মানগুলিতে ভাগ করতে পারেন এবং এগুলি একটি টেবিলের মধ্যে রাখতে পারেন। আপনার পদ্ধতি ইতিমধ্যে এটি করতে পারে।

একই ফলাফলটি অর্জন করতে আপনি একটি গতিশীল ক্যোয়ারীও ব্যবহার করতে পারেন:

DECLARE @SQL nvarchar(8000);

SET @SQL = 'SELECT * FROM TabA WHERE TabA.ID IN (' + @listOfIDs + ')';
EXECUTE (@SQL);

ধন্যবাদ, তবে আবার এমন একটি কোয়েরি পরিবর্তন করতে হবে যা আমাকে অনুমোদিত নয় allowed
এরিকট্রিপটপস

2
যদি কেউ এটি ব্যবহার করে তবে দয়া করে সচেতন হন যে যদি @listOfIDs কোনও ব্যবহারকারী দ্বারা সরবরাহ করা স্ট্রিং প্যারামিটার হয় তবে এটি এসকিউএল ইঞ্জেকশনের পক্ষে খুব ঝুঁকিপূর্ণ হতে পারে। আপনার অ্যাপ্লিকেশনটির স্থাপত্যের উপর নির্ভর করে এটি কোনও সমস্যা হতে পারে বা নাও হতে পারে।
রোগালা

@ রোগালা সম্মত হয়েছেন, ব্যবহারকারীদের প্রয়োজন অনুযায়ী তাদের নিজস্ব স্যানিটেশন করতে হবে।
মাওজ

1
@ মাওজ আমি এটি প্রতিফলিত করতে আপনার উত্তরে একটি নোট যুক্ত করার পরামর্শ দিচ্ছি। প্রত্যেকেই জানে না এবং তারা পরিণতি সম্পর্কে চিন্তা না করে সমাধানগুলি অনুলিপি করে আটকান। ডায়নামিক এসকিউএল অত্যন্ত বিপজ্জনক এবং আমি এটিকে প্লেগের মতো এড়িয়ে চলে।
রোগালা ২

@ মাওজ এছাড়াও, আমি আপনার উত্তরটি ভোট দিয়েছি না, তবে আপনি দয়া করে কয়েক মিনিট সময় নিয়ে আমার উত্তরটি দেখুন? STRING_SPLIT ফাংশনটি বেশ মিষ্টি, এবং আমি মনে করি আপনি এতে সবই থাকবেন !!
রোগালা

6

এসকিউএল সার্ভার 2016+ এবং অ্যাজুরি এসকিউএল ডেটাবেসগুলির জন্য, STRING_SPLIT ফাংশনটি যুক্ত করা হয়েছিল যা এই সমস্যার উপযুক্ত সমাধান হতে পারে। এখানে ডকুমেন্টেশনটি রয়েছে: https://docs.microsoft.com/en-us/sql/t-sql/function/string-split-transact-sql

এখানে একটি উদাহরণ:

/*List of ids in a comma delimited string
  Note: the ') WAITFOR DELAY ''00:00:02''' is a way to verify that your script 
        doesn't allow for SQL injection*/
DECLARE @listOfIds VARCHAR(MAX) = '1,3,a,10.1,) WAITFOR DELAY ''00:00:02''';

--Make sure the temp table was dropped before trying to create it
IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable;

--Create example reference table
CREATE TABLE #MyTable
([Id] INT NOT NULL);

--Populate the reference table
DECLARE @i INT = 1;
WHILE(@i <= 10)
BEGIN
    INSERT INTO #MyTable
    SELECT @i;

    SET @i = @i + 1;
END

/*Find all the values
  Note: I silently ignore the values that are not integers*/
SELECT t.[Id]
FROM #MyTable as t
    INNER JOIN 
        (SELECT value as [Id] 
        FROM STRING_SPLIT(@listOfIds, ',')
        WHERE ISNUMERIC(value) = 1 /*Make sure it is numeric*/
            AND ROUND(value,0) = value /*Make sure it is an integer*/) as ids
    ON t.[Id] = ids.[Id];

--Clean-up
DROP TABLE #MyTable;

ক্যোয়ারির ফলাফল 1,3

~ চিয়ার্স


4

শেষ পর্যন্ত আমি এই সিদ্ধান্তে পৌঁছেছি যে কোয়েরিটি কীভাবে কাজ করে তা পরিবর্তন না করে আমি ভেরিয়েবলগুলিতে মানগুলি সংরক্ষণ করতে পারি না। আমি মানগুলি ধরার জন্য এসকিউএল প্রোফাইলার ব্যবহার করেছি এবং তারপরে এটি কীভাবে কাজ করে তা দেখার জন্য তাদের কঠোরভাবে কোডে কোড করে দিয়েছি। এর মধ্যে পূর্ণসংখ্যার অ্যারেগুলির মধ্যে 18 টি ছিল এবং কারও কারও মধ্যে 30 টিরও বেশি উপাদান রয়েছে।

আমি মনে করি যে ভাষাতে কিছু অ্যাডিশনাল ডেটাটাইপগুলি প্রবর্তনের জন্য এমএস / এসকিউএল প্রয়োজন a অ্যারেগুলি বেশ সাধারণ এবং আপনি কেন সংরক্ষণ করা তদন্তে সেগুলি ব্যবহার করতে পারেন তা আমি দেখতে পাচ্ছি না।


6
এসকিউএল সার্ভারের অ্যারেগুলির দরকার হয় না, যখন এতে টেবিল-মূল্যবান প্যারামিটার এবং ভেরিয়েবল থাকে।
জন স্যান্ডার্স

1
সুতরাং আমরা কী জানি যে ক্যোয়ারীটি পূর্ণসংখ্যার একটি তালিকা ব্যবহার করে (এটি একটি অ্যারে দ্বারা প্রেরণ করা হয়েছিল?)। আমি যা বুঝতে পারি না তা হ'ল উত্তরে প্রদত্ত একটি পদ্ধতি ব্যবহার না করে আপনার প্রশ্নের কীভাবে সেগুলি ব্যবহার করা হয়েছিল using আরও কিছু প্রসঙ্গ সরবরাহ করুন এবং আমরা আপনাকে আরও সাহায্য করতে পারি।
মোজ ২

2

আপনি এটি এর মতো করতে পারবেন না, তবে আপনি এটি ভেরিয়েবলের মধ্যে সঞ্চয় করে পুরো ক্যোয়ারী কার্যকর করতে পারেন।

উদাহরণ স্বরূপ:

DECLARE @listOfIDs NVARCHAR(MAX) = 
    '1,2,3'

DECLARE @query NVARCHAR(MAX) = 
    'Select *
     From TabA
     Where TabA.ID in (' + @listOfIDs + ')'

Exec (@query)

2
পূর্ববর্তী মন্তব্যে যেমন বলা হয়েছে, আপনি কীভাবে এই ধরণের সমাধানটি প্রয়োগ করেন তার উপর নির্ভর করে সচেতন হন যে যদি @listOfIDs কোনও ব্যবহারকারী দ্বারা সরবরাহিত একটি প্যারামিটার হয় তবে এটি এসকিউএল ইঞ্জেকশনের পক্ষে ঝুঁকিপূর্ণ হতে পারে।
রোগালা 20

2

string_splitআপনি স্ট্রিংয়ের তালিকাটি ব্যবহার করছেন যদি এসকিউএল তে একটি নতুন ফাংশন বলা হয়। রেফ লিংক STRING_SPLIT (লেনদেন-এসকিউএল)

DECLARE @tags NVARCHAR(400) = 'clothing,road,,touring,bike'
SELECT value
FROM STRING_SPLIT(@tags, ',')
WHERE RTRIM(value) <> '';

আপনি এই কোয়েরিটি inনিম্নলিখিতভাবে পাস করতে পারেন :

SELECT *
  FROM [dbo].[yourTable]
  WHERE (strval IN (SELECT value FROM STRING_SPLIT(@tags, ',') WHERE RTRIM(value) <> ''))

1
দুর্ভাগ্যক্রমে দুর্ভাগ্যজনকরূপে কিন্তু কেবল এসকিউএল সার্ভার 2016 দেখায়।
30:59

0

আমি এটি ব্যবহার:

আপনার বিল্ডিংয়ে স্ক্রিপ্টে একটি টেম্প টেবিলের পরিবর্তনশীল ঘোষণা করুন:

DECLARE @ShiftPeriodList TABLE(id INT NOT NULL);

টেম্প টেবিল 2-বরাদ্দ:

IF (SOME CONDITION) 
BEGIN 
        INSERT INTO @ShiftPeriodList SELECT ShiftId FROM [hr].[tbl_WorkShift]
END
IF (SOME CONDITION2)
BEGIN
    INSERT INTO @ShiftPeriodList
        SELECT  ws.ShiftId
        FROM [hr].[tbl_WorkShift] ws
        WHERE ws.WorkShift = 'Weekend(VSD)' OR ws.WorkShift = 'Weekend(SDL)'

END

3-যখন আপনার একটি নিখরচায় বিবৃতিতে প্রয়োজন হয় তখন টেবিলটি উল্লেখ করুন:

INSERT INTO SomeTable WHERE ShiftPeriod IN (SELECT * FROM @ShiftPeriodList)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.