पूर्णांक की सूची धारण करने के लिए एसक्यूएल चर


175

मैं किसी और की SQL रिपोर्ट को डीबग करने का प्रयास कर रहा हूं और अंतर्निहित रिपोर्ट क्वेरी को SQL 2012 की क्वेरी विंडो में रखा है।

रिपोर्ट के लिए पूछे जाने वाले मापदंडों में से एक पूर्णांक की एक सूची है। यह एक बहु-चयन ड्रॉप डाउन बॉक्स के माध्यम से रिपोर्ट पर प्राप्त किया जाता है। रिपोर्ट की अंतर्निहित क्वेरी whereक्लाज सूची में इस पूर्णांक सूची का उपयोग करती है

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

मैं उस क्वेरी को संशोधित नहीं करना चाहता जो मैं डिबगिंग कर रहा हूं, लेकिन मैं यह पता नहीं लगा सकता कि SQL सर्वर पर एक वैरिएबल कैसे बनाया जाए जो इस प्रकार के डेटा को परीक्षण करने के लिए पकड़ सके।

जैसे

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

कोई डेटाटाइप नहीं है जो पूर्णांकों की सूची को पकड़ सकता है, इसलिए मैं रिपोर्ट के समान मानों के साथ अपने SQL सर्वर पर रिपोर्ट क्वेरी कैसे चला सकता हूं?


1
मुझे पता है कि मैंने डेटा डालने के लिए TVP Table Value Parmeter का उपयोग किया है, लेकिन अब सुनिश्चित करें कि इसका उपयोग कहाँ किया जा सकता है। अगली कड़ी?
पपराज़ो

2
अच्छा प्रश्न है। +1
रेअवेल्वेस

जवाबों:


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
इसके लिए धन्यवाद, लेकिन फिर से मुझे उस तरीके को फिर से लिखना होगा जिस तरह से चर को क्वेरी में पढ़ा जाता है। मुझे इसे वही रखना है।
ErickTreetops

3
यदि आपको पता नहीं है कि आईडी क्या है और यह एक क्वेरी से आता है? उदाहरण: SET @AddressIDs = (SELECT ID FROM address WHERE Account = 1234)यह क्वेरी कई आईडी लौटाएगी और मुझे यह कहते हुए एक त्रुटि मिलेगी कि उपकुंजी एक से अधिक परिणाम लौटाएगी और इसकी अनुमति नहीं है। वहाँ एक चर बनाने के लिए वैसे भी है कि एक सरणी स्टोर करेगा अगर एक उपनगर से आईडी?
राफेल मोरेरा

1
मैंने दूसरे विकल्प की कोशिश की और यह कम संख्या में रिकॉर्ड के लिए काम करता है। जब मैं Ids की संख्या बढ़ाता हूं, तो मुझे TimeOut त्रुटि मिलती है। शायद कलाकारों को प्रदर्शन में बाधा आ रही है।
यूजर एम

मूल प्रश्न का उत्तर नहीं है, लेकिन यह मेरे द्वारा पूछे गए उत्तर का उत्तर नहीं है, इसलिए मैं अच्छा हूं। मैं एक सूची <int> में एक पैरामीटर के रूप में पास करता हूं, लेकिन एसएसएमएस में परीक्षण के लिए एक स्थानीय चर बनाना चाहता हूं। यह हत्यारा है।
वेड हैटलर

महान जवाब, मुझे बहुत समय बचा लिया
अल्फ्रेडो ए।

35

चर को कुछ मान लेना निम्न है:

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

और संग्रहित प्रक्रिया इस रूप में इसका उपयोग कर रही है:

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

आप IntList बना सकते हैं और इस तरह की प्रक्रिया को कॉल कर सकते हैं:

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

या यदि आप खुद को IntList प्रदान कर रहे हैं

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

17

आप सही हैं, SQL- सर्वर में कोई डेटाटाइप नहीं है जो पूर्णांकों की सूची को पकड़ सकता है। लेकिन आप जो कर सकते हैं वह पूर्णांक की एक सूची को एक स्ट्रिंग के रूप में संग्रहीत करता है।

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

धन्यवाद, लेकिन फिर से एक क्वेरी को संशोधित करने की आवश्यकता होगी जो मुझे करने की अनुमति नहीं है।
ErickTreetops

2
यदि कोई इसका उपयोग करता है, तो कृपया ध्यान रखें कि यह SQL इंजेक्शन के लिए बहुत कमजोर हो सकता है यदि @listOfIDs एक उपयोगकर्ता द्वारा प्रदान किया गया एक स्ट्रिंग पैरामीटर है। आपके ऐप की वास्तुकला पर निर्भर करता है, यह एक मुद्दा हो सकता है या नहीं हो सकता है।
रोजला

@ रोगला सहमत, उपयोगकर्ताओं को आवश्यकतानुसार अपना स्वयं का स्वच्छता करने की आवश्यकता होगी।
मोटो

1
@ Möoz मैं इसे दर्शाने के लिए आपके उत्तर में एक नोट जोड़ने की सलाह देता हूं। हर कोई नहीं जानता है, और वे केवल परिणामों के बारे में सोचने के बिना समाधान की नकल करते हैं और पेस्ट करते हैं। डायनेमिक SQL बहुत खतरनाक है, और मैं इसे उस प्लेग से बचता हूं।
रोगला

@ Möoz इसके अलावा, मैंने आपके उत्तर को वोट नहीं दिया, लेकिन आप कृपया कुछ मिनटों का समय लें और मेरा उत्तर देखें? STRING_SPLIT फ़ंक्शन बहुत प्यारा है, और मुझे लगता है कि आप इसके ऊपर होंगे!
रोगाला

6

SQL सर्वर 2016+ और Azure SQL डेटाबेस के लिए, STRING_SPLIT फ़ंक्शन जोड़ा गया था जो इस समस्या का एक सही समाधान होगा। यहाँ प्रलेखन है: https://docs.microsoft.com/en-us/sql/t-sql/functions/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

अंत में मैं इस नतीजे पर पहुंचा कि बिना यह संशोधन किए कि क्वेरी कैसे काम करती है, मैं चर में मूल्यों को संग्रहीत नहीं कर सकता। मैंने मानों को पकड़ने के लिए SQL प्रोफाइलर का उपयोग किया और फिर इसे कैसे काम किया जाए, यह देखने के लिए उन्हें क्वेरी में कोडित किया। इन पूर्णांक सरणियों में से 18 थे और कुछ में 30 से अधिक तत्व थे।

मुझे लगता है कि भाषा में कुछ विशेष डेटाटाइप्स को लागू करने के लिए एमएस / एसक्यूएल की आवश्यकता है। ऐरे काफी आम हैं और मैं नहीं देखता कि आप उन्हें स्टोर किए गए प्रोक में इस्तेमाल क्यों नहीं कर सकते।


6
SQL सर्वर को सरणियों की आवश्यकता नहीं होती है, जब इसमें तालिका-मूल्यवान पैरामीटर और चर होते हैं।
जॉन सॉन्डर्स

1
तो हम क्या जानते हैं कि क्वेरी पूर्णांकों की एक सूची का उपयोग करता है (यह एक सरणी द्वारा पारित?)। मुझे समझ में नहीं आता है कि उत्तर में दिए गए तरीकों में से एक का उपयोग किए बिना आपकी क्वेरी कैसे उनका उपयोग कर रही थी। कुछ और संदर्भ प्रदान करें और हम आगे आपकी मदद कर सकते हैं।
मूस

2

आप इसे इस तरह से नहीं कर सकते हैं, लेकिन आप इसे एक चर में संग्रहीत पूरी क्वेरी को निष्पादित कर सकते हैं।

उदाहरण के लिए:

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

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

Exec (@query)

2
जैसा कि आप इस प्रकार के समाधान को कार्यान्वित करते हैं, इस पर निर्भर करते हुए, पिछली टिप्पणी में कहा गया है कि यह पता चलता है कि यह SQL इंजेक्शन के लिए असुरक्षित हो सकता है यदि @listOfIDs एक उपयोगकर्ता द्वारा प्रदान किया गया पैरामीटर है।
रोजला

2

string_splitयदि आप स्ट्रिंग की सूची का उपयोग कर रहे हैं, तो SQL में एक नया फ़ंक्शन है । लिंक STRING_SPLIT (Transact-SQL) का संदर्भ दें

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
दुर्भाग्यवश, लेकिन केवल SQL सर्वर 2016 दुर्भाग्य से दिखता है।
10

0

मैं इसका उपयोग करता हूं:

1-अपनी इमारत की स्क्रिप्ट में एक टेम्प टेबल चर घोषित करें:

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-जब आप WHERE स्टेटमेंट में इसकी आवश्यकता हो तो टेबल को देखें:

INSERT INTO SomeTable WHERE ShiftPeriod IN (SELECT * FROM @ShiftPeriodList)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.