টি-এসকিউএল সঞ্চিত পদ্ধতি যা একাধিক আইডি মান গ্রহণ করে


145

কোনও সঞ্চিত পদ্ধতিতে প্যারামিটার হিসাবে আইডির একটি তালিকা পাস করার ব্যবস্থা করার কি কোনও উপায় আছে?

উদাহরণস্বরূপ, আমি আমার সঞ্চিত পদ্ধতি দ্বারা 1, 2, 5, 7, 20 বিভাগগুলি ফিরিয়ে দিতে চাই। অতীতে, আমি নীচের কোডের মতো আইডির একটি কমা বিস্মৃত তালিকাতে উত্তীর্ণ হয়েছি তবে এটি করা সত্যিই নোংরা বলে মনে হচ্ছে।

এসকিউএল সার্ভার 2005 কেবলমাত্র আমার মনে হয় প্রযোজ্য সীমাবদ্ধতা।

create procedure getDepartments
  @DepartmentIds varchar(max)
as
  declare @Sql varchar(max)     
  select @Sql = 'select [Name] from Department where DepartmentId in (' + @DepartmentIds + ')'
  exec(@Sql)

আমি সদ্য পাওয়া এক্সএমএল পদ্ধতির একটি বৈকল্পিক এখানে
জেসনস

5
আপনি যদি এসকিউএল সার্ভার ২০০৮ এ থাকেন তবে আপনি একটি সারণী-মূল্যবান প্যারামিটার ব্যবহার করতে পারেন। http://www.sqlteam.com/article/sql-server-2008-table-valued-paraters
আয়ান নেলসন

এটি আমার জন্য সহায়ক ছিল: sqlmag.com/t-sql/passing-multivalued-variables-stored-procedure
জমির

উত্তর:


237

এরল্যান্ড সোমমারস্কোগ গত 16 বছর ধরে এই প্রশ্নের অনুমোদনযোগ্য উত্তর বজায় রেখেছেন: এসকিউএল সার্ভারে অ্যারে এবং তালিকা

কোনও ক্যারে একটি অ্যারে বা তালিকা পাস করার জন্য কমপক্ষে এক ডজন উপায় রয়েছে; প্রত্যেকের নিজস্ব অনন্য উপকারিতা এবং কনস রয়েছে।

এই সমস্ত বিকল্পের মধ্যে ট্রেড অফগুলি সম্পর্কে জানতে নিবন্ধটি পড়ার জন্য আমি সত্যিই পর্যাপ্ত সুপারিশ করতে পারি না ।


11

হ্যাঁ, আপনার বর্তমান সমাধানটি এসকিউএল ইনজেকশন আক্রমণে প্রবণ।

আমি যে সন্ধান পেয়েছি তার সেরা সমাধানটি এমন একটি ফাংশন ব্যবহার করা যা পাঠ্যগুলিকে শব্দের মধ্যে বিভক্ত করে (এখানে কয়েকটি পোস্ট করা হয়, বা আপনি এটি আমার ব্লগ থেকে ব্যবহার করতে পারেন ) এবং তারপরে আপনার টেবিলে যোগ দিন। কিছুটা এইরকম:

SELECT d.[Name]
FROM Department d
    JOIN dbo.SplitWords(@DepartmentIds) w ON w.Value = d.DepartmentId

14
আমি নিশ্চিত নই যে এটি "এসকিউএল ইঞ্জেকশন আক্রমণের ঝুঁকিপূর্ণ", যদি না সঞ্চিত সংগ্রহটি অবিশ্বস্ত ক্লায়েন্টদের কাছ থেকে সরাসরি কল না করা হয়, সেক্ষেত্রে আপনার বড় সমস্যা হয়। পরিষেবা স্তর কোডটি দৃ code়ভাবে টাইপ করা ডেটা (যেমন int [] বিভাগীয় আইডিস) থেকে @ ডিপার্টমেন্ট অব আইডস স্ট্রিং তৈরি করা উচিত, এক্ষেত্রে আপনি ভাল থাকবেন।
অ্যান্টনি

অসাধারণ সমাধান, @ ম্যাট হ্যামিলটন। এটি কাউকে সহায়তা করবে কিনা তা জানেন না তবে এসকিউএল সার্ভার ২০০৮-তে আমি আরও সঠিক ফলাফল পেয়েছি যখন আমি "join dbo.SplitWords (@MyParameterArray) p on CHARINDEX (p.value, d.MyFieldToSearch)>" "ব্যবহার করে পাঠ্য ক্ষেত্রগুলি অনুসন্ধান করছিলাম"
ডার্কলোকি

3

আপনি যদি মানগুলির সাথে প্রচুর পরিমাণে কাজ করতে চলেছেন তবে আপনি যে পদ্ধতিটি বিবেচনা করতে চাইতে পারেন তা হ'ল প্রথমে সেগুলি অস্থায়ী টেবিলে লিখে দেওয়া। তারপরে আপনি কেবল এতে স্বাভাবিকের মতো যোগ দিন।

এইভাবে, আপনি কেবল একবার পার্সিং করছেন।

'স্প্লিট' ইউডিএফগুলির মধ্যে একটি ব্যবহার করা সবচেয়ে সহজ, তবে এত লোক এর উদাহরণ পোস্ট করেছে, আমি বুঝতে পেরেছিলাম যে আমি অন্য পথে যাব;)

এই উদাহরণটি আপনাকে (# টিএমপিডিপেট) এ যোগদানের জন্য অস্থায়ী টেবিল তৈরি করবে এবং আপনি যে ডিপার্টমেন্টে গিয়েছেন তা পূরণ করুন I'm আমি ধরে নিচ্ছি আপনি এগুলি কমা দিয়ে আলাদা করছেন, তবে আপনি অবশ্যই - পরিবর্তন করতে পারেন এটি আপনি যা চান।

IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
    DROP TABLE #tmpDept
END

SET @DepartmentIDs=REPLACE(@DepartmentIDs,' ','')

CREATE TABLE #tmpDept (DeptID INT)
DECLARE @DeptID INT
IF IsNumeric(@DepartmentIDs)=1
BEGIN
    SET @DeptID=@DepartmentIDs
    INSERT INTO #tmpDept (DeptID) SELECT @DeptID
END
ELSE
BEGIN
        WHILE CHARINDEX(',',@DepartmentIDs)>0
        BEGIN
            SET @DeptID=LEFT(@DepartmentIDs,CHARINDEX(',',@DepartmentIDs)-1)
            SET @DepartmentIDs=RIGHT(@DepartmentIDs,LEN(@DepartmentIDs)-CHARINDEX(',',@DepartmentIDs))
            INSERT INTO #tmpDept (DeptID) SELECT @DeptID
        END
END

এটি আপনাকে একটি বিভাগের আইডি, একাধিক আইডি এবং তাদের মধ্যে কমা সহ একাধিক আইডি বা কমা এবং স্পেসের মধ্যবর্তী স্থানগুলিতে অনুমতি দেয় will

সুতরাং আপনি যদি কিছু এরকম করেন:

SELECT Dept.Name 
FROM Departments 
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name

আপনি যে ডিপার্টমেন্টে আইডি পাস করেছেন সেগুলির সমস্ত নাম আপনি দেখতে পাবেন ...

আবার, অস্থায়ী টেবিলটি জনপ্রিয় করার জন্য একটি ফাংশন ব্যবহার করে এটি সরল করা যেতে পারে ... আমি সাধারণত এটির কিছু না করে কেবল বিরক্তিকে মেরে ফেলেছিলাম :- পি

- কেভিন ফেয়ারচাইল্ড


3

আপনি এক্সএমএল ব্যবহার করতে পারেন।

যেমন

declare @xmlstring as  varchar(100) 
set @xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>' 

declare @docid int 

exec sp_xml_preparedocument @docid output, @xmlstring

select  [id],parentid,nodetype,localname,[text]
from    openxml(@docid, '/args', 1) 

কমান্ডটি sp_xML_preparedocament অন্তর্নির্মিত হয়।

এটি আউটপুট উত্পাদন করবে:

id  parentid    nodetype    localname   text
0   NULL        1           args        NULL
2   0           1           arg         NULL
3   2           2           value       NULL
5   3           3           #text       42
4   0           1           arg2        NULL
6   4           3           #text       -1

যা আপনার যা প্রয়োজন তার সমস্ত (আরও?) রয়েছে।


2

একটি সুপারস্টার এক্সএমএল পদ্ধতি, আপনি যদি কোনও সঞ্চিত পদ্ধতি ব্যবহার করতে চান এবং বিভাগ আইডির কমা দ্বারা পৃথক করা তালিকাটি পাস করতে চান:

Declare @XMLList xml
SET @XMLList=cast('<i>'+replace(@DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from @XMLList.nodes('i') x(i))

সমস্ত কৃতিত্ব গুরু ব্র্যাড শুলজের ব্লগে যায়


-3

আর একবার চেষ্টা কর:

@list_of_params varchar(20) -- value 1, 2, 5, 7, 20 

SELECT d.[Name]
FROM Department d
where @list_of_params like ('%'+ CONVERT(VARCHAR(10),d.Id)  +'%')

খুব সহজ.


1
খুব সহজ - এবং খুব ভুল। তবে আপনি যদি আপনার কোডটিতে সমস্যাটি ঠিক করেন তবে এটি খুব ধীর হবে। বিশদগুলির জন্য গৃহীত উত্তরে "সত্যই ধীর পদ্ধতি" লিঙ্কটি দেখুন।
সেবাস্তিয়ান মেইন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.