অনুচ্ছেদে একটি এসকিউএল প্যারামিটারাইজ করুন


1041

আমি INএই জাতীয় মত একটি ভেরিয়েবল সংখ্যার যুক্ত একটি ক্লজ সম্বলিত একটি কোয়েরিটিকে কীভাবে পরামিতি করব ?

SELECT * FROM Tags 
WHERE Name IN ('ruby','rails','scruffy','rubyonrails')
ORDER BY Count DESC

এই ক্যোয়ারিতে, আর্গুমেন্টের সংখ্যা 1 থেকে 5 পর্যন্ত যে কোনও জায়গায় হতে পারে।

আমি এটির (বা এক্সএমএল) জন্য কোনও উত্সর্গীকৃত সঞ্চিত পদ্ধতি ব্যবহার না করা পছন্দ করব তবে এসকিউএল সার্ভার ২০০৮-এর সাথে সুনির্দিষ্ট কিছু উপায় থাকলে , আমি এটির জন্য উন্মুক্ত।



উত্তর:


316

এখানে আমি একটি দ্রুত এবং নোংরা কৌশল ব্যবহার করেছি:

SELECT * FROM Tags
WHERE '|ruby|rails|scruffy|rubyonrails|'
LIKE '%|' + Name + '|%'

সুতরাং এখানে সি # কোড:

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
const string cmdText = "select * from tags where '|' + @tags + '|' like '%|' + Name + '|%'";

using (SqlCommand cmd = new SqlCommand(cmdText)) {
   cmd.Parameters.AddWithValue("@tags", string.Join("|", tags);
}

দুটি সতর্কতা:

  • অভিনয়টি ভয়াবহ terrible LIKE "%...%"প্রশ্নগুলি সূচিবদ্ধ হয় না।
  • আপনার কোনও |খালি বা নাল ট্যাগ নেই বা এটি কাজ করবে না তা নিশ্চিত করুন

এটি সম্পাদন করার অন্যান্য উপায় আছে যা কিছু লোক ক্লিনার হিসাবে বিবেচনা করতে পারে, তাই দয়া করে পড়া চালিয়ে যান।


119
এটি
হেলা

13
হ্যাঁ, এটি একটি টেবিল স্ক্যান। 10 টি সারির জন্য দুর্দান্ত, 100,000 এর জন্য লাউস।
হার্টং

17
আপনি যে ট্যাগগুলিতে পাইপ রয়েছে সেগুলি পরীক্ষা করে দেখুন।
জোয়েল কোহোর্ন

17
এটি এমনকি প্রশ্নের উত্তর দেয় না। মঞ্জুর, প্যারামিটারগুলি কোথায় যুক্ত করা যায় তা সহজেই দেখা যায়, তবে যদি ক্যোয়ারিকে প্যারামিটারাইজ করার জন্য বিরক্ত না করে তবে আপনি কীভাবে এই সমাধানটি গ্রহণ করতে পারেন? এটি কেবলমাত্র @ মার্ক ব্র্যাকেটের চেয়ে সহজ দেখাচ্ছে কারণ এটি প্যারামিটারাইজড নয়।
tvanfosson

21
যদি আপনার ট্যাগটি 'রুবি | রেল' হয় তবে কী হবে। এটি মিলবে, যা ভুল হবে। আপনি যখন এই জাতীয় সমাধানগুলি রোল করেন, আপনাকে অবশ্যই নিশ্চিত করতে হবে যে ট্যাগগুলিতে পাইপ রয়েছে না, বা সেগুলি স্পষ্টভাবে ফিল্টার আউট করতে হবে: ট্যাগগুলি থেকে * নির্বাচন করুন যেখানে '| রুবি | রেলস | জঞ্জাল | রুবিওনরইলস |' '% |' এর মতো + নাম + '|%' এবং নাম '%!%' এর মতো নয়
এ কে

729

আপনি প্রতিটি মানকে প্যারামিটারাইজ করতে পারেন , তাই এরকম কিছু:

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

string inClause = string.Join(", ", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

যা আপনাকে দেবে:

cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"

না, এটি এসকিউএল ইঞ্জেকশনটির জন্য উন্মুক্ত নয় । কমান্ডটেক্সটে কেবলমাত্র ইনজেকশনের পাঠ্যটি ব্যবহারকারীর ইনপুটের ভিত্তিতে নয়। এটি সম্পূর্ণরূপে হার্ডকোডযুক্ত "@ ট্যাগ" উপসর্গ এবং একটি অ্যারের সূচকের উপর ভিত্তি করে। সূচক সর্বদা একটি পূর্ণসংখ্যার হবে, ব্যবহারকারী উত্পন্ন হয় না, এবং নিরাপদ is

ব্যবহারকারীর ইনপুট করা মানগুলি এখনও পরামিতিগুলিতে স্টাফ করা হয়, সুতরাং সেখানে কোনও দুর্বলতা নেই।

সম্পাদনা:

ইনজেকশনটি উদ্বেগের বিষয়টি আলাদা করে রাখুন, খেয়াল করুন যে কমান্ড পাঠ্যটি পরিবর্তনশীল সংখ্যক পরামিতি (উপরে হিসাবে) সংযুক্ত করার জন্য ক্যাশেড কোয়েরিগুলির সুবিধা গ্রহণের এসকিউএল সার্ভারের ক্ষমতাকে বাধা দেয়। নেট ফলাফলটি হ'ল আপনি প্রায় অবশ্যই প্রথম স্থানে প্যারামিটারগুলি ব্যবহার করার মান হারাবেন (এসকিউএল নিজেই প্রেডিকেট স্ট্রিংগুলি সন্নিবেশ করার বিপরীতে)।

ক্যাশেড ক্যোয়ারী পরিকল্পনাগুলি মূল্যবান নয় এমন নয়, তবে আইএমও এই কোয়েরিটি এর থেকে বেশি সুবিধা দেখতে যথেষ্ট জটিল নয় complicated সংকলন ব্যয়গুলি এক্সিকিউশন ব্যয়ের কাছাকাছি যেতে পারে (বা এমনকি এটিও ছাড়িয়ে যেতে পারে), আপনি এখনও মিলিসেকেন্ডে কথা বলছেন।

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

এছাড়াও, এসকিউএল সার্ভার and এবং তারপরে অনুসন্ধানগুলি স্বয়ংক্রিয়ভাবে প্যারামিটারাইজ করবে , সুতরাং কোনও পারফরম্যান্সের দিক থেকে পরামিতিগুলি ব্যবহার করা সত্যিই প্রয়োজনীয় নয় - তবে এটি কোনও সুরক্ষা দৃষ্টিকোণ থেকে গুরুত্বপূর্ণ - বিশেষত এর মতো ব্যবহারকারী ইনপুটযুক্ত ডেটা সহ।


2
মূলত "সম্পর্কিত" প্রশ্নের আমার উত্তর এবং স্পষ্টতই সেরা সমাধান যেহেতু এটি ব্যাখ্যামূলক (অনেক বেশি শক্ত) এর চেয়ে গঠনমূলক এবং দক্ষ efficient
tvanfosson

49
লিনকিউ থেকে এসকিউএল এটি কীভাবে করে, বিটিডাব্লু
মার্ক সিডেড

3
@ বিশুদ্ধ: এর পুরো বিষয়টি হ'ল এসকিউএল ইনজেকশন এড়ানো, যা আপনি যদি গতিশীল এসকিউএল ব্যবহার করেন তবে আপনি ঝুঁকির মধ্যে পড়বেন।
রায়

4
@ ডেটা গড - হ্যাঁ, আমি মনে করি আপনার যদি 2100 টির বেশি ট্যাগের প্রয়োজন হয় তবে আপনার আলাদা সমাধান দরকার। তবে গড় ট্যাগের দৈর্ঘ্য <3 ​​অক্ষর (যদি আপনার পাশাপাশি একটি ডেলিমিটারও প্রয়োজন হয়) কেবল বাসরব 2100 এ পৌঁছাতে পারে। msdn.microsoft.com/en-us/library/ms143432.aspx
মার্ক

2
@ বোনকোডিগো - আপনার নির্বাচিত মানগুলি একটি অ্যারেতে রয়েছে; আপনি কেবল অ্যারের উপরে লুপ করেন এবং প্রতিটিটির জন্য একটি পরামিতি (সূচক সহ প্রত্যয়যুক্ত) যুক্ত করেন।
মার্ক ব্রাকেট

249

এসকিউএল সার্ভার ২০০৮-এর জন্য, আপনি একটি টেবিলের মূল্যবান পরামিতি ব্যবহার করতে পারেন । এটি কিছুটা কাজ, তবে এটি আমার অন্যান্য পদ্ধতির চেয়ে তর্কযুক্ত পরিষ্কার ।

প্রথমত, আপনাকে একটি প্রকার তৈরি করতে হবে

CREATE TYPE dbo.TagNamesTableType AS TABLE ( Name nvarchar(50) )

তারপরে, আপনার ADO.NET কোডটি দেখতে এমন দেখাচ্ছে:

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
cmd.CommandText = "SELECT Tags.* FROM Tags JOIN @tagNames as P ON Tags.Name = P.Name";

// value must be IEnumerable<SqlDataRecord>
cmd.Parameters.AddWithValue("@tagNames", tags.AsSqlDataRecord("Name")).SqlDbType = SqlDbType.Structured;
cmd.Parameters["@tagNames"].TypeName = "dbo.TagNamesTableType";

// Extension method for converting IEnumerable<string> to IEnumerable<SqlDataRecord>
public static IEnumerable<SqlDataRecord> AsSqlDataRecord(this IEnumerable<string> values, string columnName) {
    if (values == null || !values.Any()) return null; // Annoying, but SqlClient wants null instead of 0 rows
    var firstRecord = values.First();
    var metadata = SqlMetaData.InferFromValue(firstRecord, columnName);
    return values.Select(v => 
    {
       var r = new SqlDataRecord(metadata);
       r.SetValues(v);
       return r;
    });
}

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

4
@ জেফএটউড - আপনি কি কোয়ের মতো কোনও কিছুর প্রতিস্থাপনের চেষ্টা করেছেন SELECT * FROM tags WHERE tags.name IN (SELECT name from @tvp);? তত্ত্বগতভাবে, এটি সত্যই দ্রুততম পদ্ধতির হওয়া উচিত। আপনি প্রাসঙ্গিক সূচকগুলি ব্যবহার করতে পারেন (উদাহরণস্বরূপ ট্যাগ নামের একটি সূচক যা INCLUDEগণনাটি আদর্শ হতে পারে), এবং এসকিউএল সার্ভারকে সমস্ত ট্যাগ এবং তাদের সংখ্যা ধরে রাখতে কয়েকটি চেষ্টা করা উচিত। পরিকল্পনাটি কেমন দেখাচ্ছে?
নিক চ্যামাস

9
আমি এটিও পরীক্ষা করে দেখেছি এবং এটি হালকা হিসাবে দ্রুত (স্ট্রিংয়ের একটি বৃহত গঠনের তুলনায়)। প্যারামিটারটি সেট করতে আমার কিছুটা সমস্যা হয়েছিল যদিও আমি ক্রমাগত "ইনটামো [[] থেকে আইইনুমেয়রিয়াল 1 তে রূপান্তর করতে ব্যর্থ" হয়ে যাচ্ছিলাম। যাইহোক, এটি সমাধান করুন এবং এখানে আমি একটি নমুনা তৈরি করেছি পেস্টবিন.com
ফ্রেড্রিক জোহানসন

6
@ ফ্রেড্রিকজোহানসন - ১৩০ টি উর্ধ্বগতির মধ্যে আপনি সম্ভবত একমাত্র রান যে এটি চালানোর চেষ্টা করেছেন! দস্তাবেজগুলি পড়তে আমি ভুল করেছিলাম, এবং আপনার আসলে একটি আইনিংরেবল <স্ক্যালডাটা রেকর্ড> দরকার, কেবল কোনও আইএনউমারেবল নয়। কোড আপডেট করা হয়েছে।
মার্ক ব্র্যাকেট 18

3
@ মার্কব্রেকেট একটি আপডেটের সাথে দুর্দান্ত! প্রকৃতপক্ষে এই কোডটি আমার জন্য সত্যিই সেই দিনটি বাঁচিয়েছে যেহেতু আমি লুসিন অনুসন্ধান-সূচকে জিজ্ঞাসা করছি এবং এটি মাঝে মাঝে 50.000 এরও বেশি বা এমন হিট দেয় যা এসকিউএল সার্ভারের বিরুদ্ধে ডাবল চেক করা দরকার - সুতরাং আমি একটি অ্যারের তৈরি করব [] (নথি / এসকিউএল কী) এবং তারপরে উপরের কোডটি আসে The পুরো ওপি এখন 200 মিমি এর চেয়ে কম সময় নেয় :)
ফ্রেড্রিক জোহানসন

188

মূল প্রশ্নটি ছিল "আমি কীভাবে কোনও ক্যোয়ারিকে প্যারামিটারাইজ করব ..."

আমাকে এখনই জানিয়ে দিন, এটি মূল প্রশ্নের উত্তর নয় । অন্যান্য ভাল উত্তরে ইতিমধ্যে এর কিছু বিক্ষোভ রয়েছে।

এই বলে দিয়েছিলেন, এগিয়ে যান এবং এই উত্তরটি পতাকাঙ্কিত করুন, এটিকে নিম্নোক্ত করুন, উত্তর হিসাবে চিহ্নিত করুন না ... আপনি যা বিশ্বাস করেন ঠিক তাই করুন।

আমি (এবং অন্য 231 জন) যে পছন্দসই উত্তরে উত্তোলন করেছি সেই পছন্দসই উত্তরের জন্য মার্ক ব্র্যাকেটের উত্তর দেখুন। তার উত্তরে প্রদত্ত পদ্ধতির সাহায্যে 1) বাইন্ড ভেরিয়েবলের কার্যকর ব্যবহারের জন্য এবং 2) পূর্বাভাসের জন্য ব্যয় করতে সক্ষম হবে।

নির্বাচিত উত্তর

আমি এখানে যা সম্বোধন করতে চাই তা হ'ল জোয়েল স্পলস্কির উত্তরে দেওয়া পদ্ধতির উত্তরটি সঠিক উত্তর হিসাবে "নির্বাচিত"।

জোল স্পলস্কির পদ্ধতির চালাক। এবং এটি যুক্তিসঙ্গতভাবে কাজ করে, এটি অনুমানযোগ্য আচরণ এবং অনুমানযোগ্য পারফরম্যান্স প্রদর্শন করতে চলেছে, "সাধারণ" মানগুলি দেওয়া হয় এবং NUL এবং খালি স্ট্রিংয়ের মতো আদর্শ প্রান্তের ক্ষেত্রে। এবং এটি কোনও নির্দিষ্ট প্রয়োগের জন্য যথেষ্ট হতে পারে be

তবে এই পদ্ধতির সাধারণীকরণের ক্ষেত্রে, আসুন আরও অস্পষ্ট কোণার কেসগুলিও বিবেচনা করুন, যেমন Nameকলামটিতে ওয়াইল্ডকার্ডের অক্ষর রয়েছে (যেমন লাইক প্রিকেট দ্বারা স্বীকৃত)) আমি যে ওয়াইল্ডকার্ড চরিত্রটি দেখতে পাই যা সবচেয়ে বেশি ব্যবহৃত হয় তা হ'ল %(শতাংশের চিহ্ন)। সুতরাং আসুন এখন এখানে এটি মোকাবেলা, এবং পরে অন্যান্য ক্ষেত্রে যেতে হবে।

% চরিত্র নিয়ে কিছু সমস্যা

একটি নামের মান বিবেচনা করুন 'pe%ter' । (এখানে উদাহরণগুলির জন্য, আমি কলামের নামের জায়গায় একটি আক্ষরিক স্ট্রিং মান ব্যবহার করি)) pe 'পে% টের' নামের একটি মান সহ একটি সারি ফর্মের কোয়েরিতে ফিরে আসবে:

select ...
 where '|peanut|butter|' like '%|' + 'pe%ter' + '|%'

তবে সেই একই সারিটি হবে না অনুসন্ধানের পদগুলির ক্রমটি বিপরীত হলে ফেরানো :

select ...
 where '|butter|peanut|' like '%|' + 'pe%ter' + '|%'

আমরা যে আচরণটি পর্যবেক্ষণ করি তা এক ধরণের বিজোড়। তালিকায় অনুসন্ধান শর্তাবলী ক্রম পরিবর্তন ফলাফল পরিবর্তন করে।

এটি প্রায় না বলে চলে যায় যে আমরা নাও চাই pe%ter চিনাবাদাম মাখনের সাথে মেলাতে , তার যতই পছন্দ হোক না কেন।

অস্পষ্ট কোণার কেস

(হ্যাঁ, আমি সম্মত হব যে এটি একটি অস্পষ্ট মামলা Pro সম্ভবত এটির পরীক্ষা করার সম্ভাবনা নেই a আমরা কলামের মানে কোনও ওয়াইল্ডকার্ডের আশা করবো না ass আমরা ধরে নিতে পারি যে অ্যাপ্লিকেশনটি এই জাতীয় মান সংরক্ষণ করা থেকে বিরত করে But তবে আমার অভিজ্ঞতায় আমি খুব কমই এমন একটি ডাটাবেস সীমাবদ্ধতা দেখেছি যা বিশেষত অক্ষরের বা নিদর্শনগুলিকে অস্বীকার করে যা একটি ডানদিকে ওয়াইল্ডকার্ড হিসাবে বিবেচিত হবে LIKE তুলনামূলক অপারেটরের ।

একটি গর্ত প্যাচিং

এই গর্তটি প্যাচ করার জন্য একটি উপায় হ'ল %ওয়াইল্ডকার্ড চরিত্রটি এড়ানো । (অপারেটরের পলায়ন ধারাটির সাথে পরিচিত না এমন কারও জন্য, এসকিউএল সার্ভার ডকুমেন্টেশনের লিঙ্ক এখানে ।

select ...
 where '|peanut|butter|'
  like '%|' + 'pe\%ter' + '|%' escape '\'

এখন আমরা আক্ষরিক% মেলতে পারি। অবশ্যই, যখন আমাদের একটি কলামের নাম থাকবে, আমাদের গতিশীলভাবে ওয়াইল্ডকার্ড থেকে পালাতে হবে। আমরা REPLACEফাংশনটি %চরিত্রের উপস্থিতিগুলি সন্ধান করতে এবং প্রত্যেকের সামনে একটি ব্যাকস্ল্যাশ অক্ষর সন্নিবেশ করতে পারি:

select ...
 where '|pe%ter|'
  like '%|' + REPLACE( 'pe%ter' ,'%','\%') + '|%' escape '\'

সুতরাং এটি% ওয়াইল্ডকার্ড দিয়ে সমস্যার সমাধান করে। প্রায়।

পালাও পালাও

আমরা বুঝতে পারি যে আমাদের সমাধানটি আরও একটি সমস্যা চালু করেছে। পালানোর চরিত্র। আমরা দেখতে পাচ্ছি যে আমাদেরও পালানোর চরিত্রের যে কোনও ঘটনা থেকে নিজেকে বাঁচতে হবে। এবার, আমরা ব্যবহার! পালানোর চরিত্র হিসাবে:

select ...
 where '|pe%t!r|'
  like '%|' + REPLACE(REPLACE( 'pe%t!r' ,'!','!!'),'%','!%') + '|%' escape '!'

আন্ডারস্কোরও

এখন যেহেতু আমরা একটি রোল করছি, আমরা অন্য একটি REPLACEহ্যান্ডেলটিকে আন্ডারস্কোর ওয়াইল্ডকার্ড যুক্ত করতে পারি । এবং কেবল মজাদার জন্য, এবার, আমরা the পালানোর চরিত্র হিসাবে ব্যবহার করব।

select ...
 where '|p_%t!r|'
  like '%|' + REPLACE(REPLACE(REPLACE( 'p_%t!r' ,'$','$$'),'%','$%'),'_','$_') + '|%' escape '$'

আমি পালানোর পক্ষে এই পদ্ধতির পছন্দ করি কারণ এটি ওরাকল এবং মাইএসকিউএল পাশাপাশি এসকিউএল সার্ভারেও কাজ করে। (আমি সাধারণত পালানোর চরিত্র হিসাবে \ ব্যাকস্ল্যাশ ব্যবহার করি, যেহেতু আমরা নিয়মিত অভিব্যক্তিগুলিতেই সেই চরিত্রটি ব্যবহার করি But তবে কেন কনভেনশনে বাধা থাকবেন!

P অসাধারণ বন্ধনীগুলি

এসকিউএল সার্ভার এছাড়াও ওয়াইল্ডকার্ড অক্ষরগুলিকে বন্ধনীতে আবদ্ধ করে তাকে আক্ষরিক হিসাবে বিবেচনা করার অনুমতি দেয় []। সুতরাং আমরা কমপক্ষে এসকিউএল সার্ভারের জন্য এখনও ঠিক করতে পারিনি। যেহেতু জোড়া বন্ধনীগুলির বিশেষ অর্থ রয়েছে, তাই আমাদের সেগুলিও পালানো দরকার। যদি আমরা বন্ধনীগুলি সঠিকভাবে পালাতে পারি তবে কমপক্ষে আমাদের বন্ধনীগুলির মধ্যে হাইফেন -এবং ক্যারেটটি নিয়ে বিরক্ত ^করার দরকার নেই। এবং আমরা কোন চলে যাবে %এবং_ বন্ধনীর হাত থেকে রক্ষা পেয়েছি অক্ষরগুলি রক্ষা করতে পারি, কারণ আমরা বন্ধনীগুলির বিশেষ অর্থ অক্ষম করব।

বন্ধনীগুলির জোড়া মেলানো সন্ধান করা এত কঠিন হওয়া উচিত নয়। সিঙ্গলটন% এবং _ এর সংঘটনগুলি পরিচালনা করার চেয়ে কিছুটা বেশি কঠিন। (দ্রষ্টব্য যে কেবল বন্ধনীর সমস্ত ঘটনা থেকে রেহাই যথেষ্ট নয়, কারণ একটি সিঙ্গলটন বন্ধনীকে আক্ষরিক হিসাবে বিবেচনা করা হয় এবং এড়াতে হবে না more আরও পরীক্ষার কেস না চালিয়ে আমি হ্যান্ডেল করার চেয়ে যুক্তিটি কিছুটা ঝাপসা হয়ে উঠছে more ।)

ইনলাইন এক্সপ্রেশন অগোছালো হয়ে যায়

এসকিউএল-তে এই ইনলাইন এক্সপ্রেশনটি দীর্ঘতর এবং কৃপণ হয়ে উঠছে। আমরা সম্ভবত এটি কার্যকর করে তুলতে পারি, তবে স্বর্গ যে দরিদ্র আত্মাকে পিছনে আসে এবং তা বোঝাতে হয় help আমি যতটা অনুরাগী ইনলাইন এক্সপ্রেশনগুলির জন্য আছি, আমি এখানে একটি ব্যবহার করার প্রবণতা করি না, মূলত কারণ আমি গণ্ডগোলের কারণ ব্যাখ্যা করে কোনও মন্তব্য দিতে চাই না এবং এর জন্য ক্ষমা চাইছি।

কোন অনুষ্ঠান কোথায়?

ঠিক আছে, সুতরাং, যদি আমরা এসকিউএল-তে কোনও ইনলাইন এক্সপ্রেশন হিসাবে এটি পরিচালনা না করি তবে আমাদের কাছে নিকটতম বিকল্পটি একটি ব্যবহারকারী সংজ্ঞায়িত ফাংশন। এবং আমরা জানি যে জিনিসগুলি কোনও গতি বাড়িয়ে তুলবে না (যদি না আমরা এর উপরে কোনও সূচকটি সংজ্ঞায়িত করতে পারি না, যেমন আমরা ওরাকলকে দিয়ে করতে পারি)) যদি আমাদের কোনও ফাংশন তৈরি করতে পাওয়া যায়, তবে এসকিউএলকে কল করার কোডটিতে আমরা এটি আরও ভাল করতে পারি might বিবৃতি।

এবং এই ফাংশনটির আচরণে কিছু পার্থক্য থাকতে পারে, যা ডিবিএমএস এবং সংস্করণে নির্ভর করে। (আপনার সকল জাভা বিকাশকারীকে চিৎকার করে আওয়াজ দেওয়া যায় যে আন্তঃদেশীয়ভাবে কোনও ডাটাবেস ইঞ্জিন ব্যবহার করতে সক্ষম হতে আগ্রহী))

ডোমেইন সংক্রান্ত জ্ঞান

কলামের জন্য আমাদের ডোমেনটির বিশেষ জ্ঞান থাকতে পারে, (এটি কলামের জন্য প্রয়োগযোগ্য অনুমতিযোগ্য মানের সেট। আমরা একটি অগ্রাধিকার জানতে পারি যে কলামে সঞ্চিত মানগুলি কখনই শতকরা চিহ্ন, আন্ডারস্কোর বা বন্ধনী ধারণ করে না এই ক্ষেত্রে, আমরা কেবলমাত্র একটি দ্রুত মন্তব্য অন্তর্ভুক্ত করব যে cases কেসগুলি আচ্ছাদিত।

কলামে সঞ্চিত মানগুলি% বা _ অক্ষরের জন্য মঞ্জুরি দিতে পারে, তবে একটি সীমাবদ্ধতার জন্য সেই মানগুলি পলায়ন করা প্রয়োজন, সম্ভবত একটি সংজ্ঞায়িত অক্ষর ব্যবহার করা যেতে পারে, যেমন মানগুলি তুলনা "নিরাপদ"। আবার মানগুলির অনুমোদিত সেট সম্পর্কে একটি তাত্পর্যপূর্ণ মন্তব্য এবং বিশেষত কোন চরিত্রটি একটি পালানোর চরিত্র হিসাবে ব্যবহৃত হয় এবং জোয়েল স্পলস্কির পদ্ধতির সাথে চলে।

তবে বিশেষায়িত জ্ঞান এবং গ্যারান্টি থেকে অনুপস্থিত, আমাদের পক্ষে কমপক্ষে সেই অস্পষ্ট কোণার কেসগুলি পরিচালনা করার বিষয়ে বিবেচনা করা এবং আচরণটি যুক্তিসঙ্গত এবং "স্পেসিফিকেশন অনুসারে" কিনা তা বিবেচনা করা গুরুত্বপূর্ণ।


অন্যান্য ইস্যু পুনরুক্ত

আমি বিশ্বাস করি অন্যরা ইতিমধ্যে বিবেচিত অন্যান্য সাধারণ ক্ষেত্রগুলির মধ্যে ইতিমধ্যে যথেষ্ট পরিমাণে নির্দেশ করেছে:

  • এসকিউএল ইঞ্জেকশন (ব্যবহারকারীর সরবরাহিত তথ্য হিসাবে যা প্রদর্শিত হবে তা গ্রহণ করে এবং এসকিউএল পাঠ্যটিতে বাইন্ড ভেরিয়েবলের মাধ্যমে সরবরাহের পরিবর্তে এটি অন্তর্ভুক্ত করে। এটি মোকাবেলার উপায়:

  • ইন্ডেক্স সেকেন্ডের চেয়ে সূচক স্ক্যান ব্যবহার করে অপ্টিমাইজার পরিকল্পনা, ওয়াইল্ডকার্ডগুলি থেকে বাঁচার জন্য একটি এক্সপ্রেশন বা ফাংশনের সম্ভাব্য প্রয়োজন (এক্সপ্রেশন বা ফাংশনের উপর সম্ভাব্য সূচি)

  • বাইন্ড ভেরিয়েবলের প্রভাবের পরিমাণের ক্ষেত্রে আক্ষরিক মানগুলি ব্যবহার করা যায় ala


উপসংহার

আমি জোয়েল স্পলস্কির অ্যাপ্রোচ পছন্দ করি। এটা চালাক। এবং এটি কাজ করে।

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

হ্যাঁ, আমি আসল প্রশ্ন থেকে অনেক দূরে চলে এসেছি। তবে আমি যে প্রশ্নের জন্য "নির্বাচিত" উত্তর দিয়ে একটি গুরুত্বপূর্ণ বিষয় হিসাবে বিবেচনা করি সে সম্পর্কে এই নোটটি কোথায় রাখবেন?


আপনি যদি প্যারামিটারাইজড কোয়েরি ব্যবহার করেন বা পছন্দ করেন তবে দয়া করে আমাদের জানান? এই বিশেষ ক্ষেত্রে 'প্যারামিটারাইজড ক্যোয়ারি ব্যবহার করুন' এর মূল নিয়মের উপর ঝাঁপিয়ে পড়া এবং মূল ভাষার সাথে স্যানিটাইজ করা কি সঠিক? অনেক ধন্যবাদ
লুইস সিকোট

2
@ লুইস: হ্যাঁ, আমি এসকিউএল স্টেটমেন্টগুলিতে বাইন্ড ভেরিয়েবলগুলি ব্যবহার করতে পছন্দ করি এবং কেবলমাত্র বাইন্ড ভেরিয়েবলগুলি এগুলি ব্যবহার করার সময় এড়ানো হবে যখন কোনও পারফরম্যান্স সমস্যার কারণ হয়। মূল সমস্যাটির জন্য আমার আদর্শিক প্যাটার্নটি হ'ল আইএন তালিকার প্রয়োজনীয় সংখ্যক স্থানধারীর সাথে এসকিউএল স্টেটমেন্টটি গতিশীলভাবে তৈরি করা এবং তারপরে প্রতিটি মানকে স্থানধারীদের মধ্যে একটিতে আবদ্ধ করা। মার্ক ব্র্যাকেটের উত্তরটি দেখুন, যা আমি (এবং অন্য 231 জন) উপরে উত্সাহিত উত্তর।
spencer7593

133

আপনি স্ট্রিং হিসাবে প্যারামিটারটি পাস করতে পারেন

সুতরাং আপনার স্ট্রিং আছে

DECLARE @tags

SET @tags = ruby|rails|scruffy|rubyonrails

select * from Tags 
where Name in (SELECT item from fnSplit(@tags, ‘|’))
order by Count desc

তারপরে আপনাকে যা করতে হবে তা হ'ল 1 প্যারামিটার হিসাবে স্ট্রিংটি পাস করতে হবে।

আমি যে স্প্লিট ফাংশনটি ব্যবহার করি তা এখানে।

CREATE FUNCTION [dbo].[fnSplit](
    @sInputList VARCHAR(8000) -- List of delimited items
  , @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(8000))

BEGIN
DECLARE @sItem VARCHAR(8000)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
 BEGIN
 SELECT
  @sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))),
  @sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))

 IF LEN(@sItem) > 0
  INSERT INTO @List SELECT @sItem
 END

IF LEN(@sInputList) > 0
 INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END

2
আপনি এই পদ্ধতির সাথে টেবিল-ফাংশনেও যোগ দিতে পারেন।
মাইকেল হরেন

আমি ওরাকলে এর অনুরূপ একটি সমাধান ব্যবহার করি। অন্যান্য সমাধানগুলির মতো কিছুটিকে আবার পার্স করার দরকার নেই।
লেইফ রিফেল

9
এটি একটি খাঁটি ডাটাবেস পদ্ধতির, অন্যটির জন্য ডাটাবেসের বাইরে কোডের প্রয়োজন require
ডেভিড বাসরব

এটি কি কোনও টেবিল স্ক্যান করতে পারে বা এটি সূচি ইত্যাদির সুবিধা নিতে পারে?
খাঁটি.ক্রোম

এসকিউএল টেবিল ফাংশন (কমপক্ষে ২০০৫ এর পরে) এর বিপরীতে ক্রস অ্যাপ্লাই ব্যবহার করা আরও ভাল হবে, যা মূলত ফিরে আসা টেবিলের সাথে যোগ দেয়
অ্যাডল্ফ রসুন

66

আমি আজ পডকাস্টে জেফ / জোয়েল সম্পর্কে কথাটি শুনেছি ( পর্ব 34 , 2008-12-16 (এমপি 3, 31 এমবি), 1 এইচ 03 মিনিট 38 সেকেন্ড - 1 এইচ 06 মিনিট 45 সেকেন্ড), এবং আমি ভেবেছিলাম স্ট্যাক ওভারফ্লোটি আবার ফিরে পেয়েছি লিনকিউ এসকিউএল- তে ব্যবহার করছিল , তবে সম্ভবত এটি খালি হয়ে গেছে। এখানে লিংক থেকে এসকিউএল একই জিনিস।

var inValues = new [] { "ruby","rails","scruffy","rubyonrails" };

var results = from tag in Tags
              where inValues.Contains(tag.Name)
              select tag;

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

যাইহোক, আপনি যদি এটি অত্যন্ত প্রস্তাবিত লিনকুইপ্যাডে চালান এবং এই কোয়েরিটি চালান, আপনি এসকিউএল লিনকিউ সরবরাহকারী প্রকৃত এসকিউএল দেখতে পারেন। এটি আপনাকে প্রতিটি মানকে একটি INশৃঙ্খলে পরিণত করে দেখায় getting


50

আপনি। নেট থেকে কল দিলে আপনি ড্যাপার ডট নেট ব্যবহার করতে পারেন :

string[] names = new string[] {"ruby","rails","scruffy","rubyonrails"};
var tags = dataContext.Query<Tags>(@"
select * from Tags 
where Name in @names
order by Count desc", new {names});

এখানে ড্যাপার চিন্তাভাবনা করে, তাই আপনার দরকার নেই। লিনকিউ থেকে এসকিউএল এর সাথে অবশ্যই এর কিছু পাওয়া সম্ভব :

string[] names = new string[] {"ruby","rails","scruffy","rubyonrails"};
var tags = from tag in dataContext.Tags
           where names.Contains(tag.Name)
           orderby tag.Count descending
           select tag;

11
যা আমরা এই পৃষ্ঠায় যা ব্যবহার করি তা ঘটবে, আসল প্রশ্নের জন্য জিজ্ঞাসা করা হয়েছিল ( দ্যাপার
স্যাম


নামগুলি দীর্ঘ হলে এটি পড়ে যায়
cs0815

29

এটি সম্ভবত এটি করার অর্ধেক বাজে উপায়, আমি এটি একবার ব্যবহার করেছি, বরং কার্যকর ছিল।

আপনার লক্ষ্যগুলির উপর নির্ভর করে এটি কার্যকর হতে পারে।

  1. একটি কলাম সহ একটি টেম্প টেবিল তৈরি করুন ।
  2. INSERT প্রতিটি কলামটিতে কলামের মান।
  3. একটি ব্যবহারের পরিবর্তে IN, আপনি কেবলমাত্র আপনার মানক JOINবিধিগুলি ব্যবহার করতে পারেন । (নমনীয়তা ++)

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

আমি কখনই ঠিক কত দ্রুত তা প্রোফাইলিং করতে পারি নি , তবে আমার পরিস্থিতিতে এটির প্রয়োজন ছিল।


এটা মোটেও বাজে নয়! আরও বেশি, এটি একটি খুব পরিষ্কার উপায় আইএমএইচও। এবং যদি আপনি কার্যনির্বাহী পরিকল্পনার দিকে নজর দেন তবে আপনি দেখতে পাবেন যে এটি আইএন ধারাটির মতো। কোনও টেম্প টেবিলের পরিবর্তে, আপনি সূচীগুলির সাথে একটি স্থির টেবিলও তৈরি করতে পারেন, যেখানে আপনি SESSIONID এর সাথে পরামিতিগুলি একসাথে সঞ্চয় করেন।
এসকিউএল পুলিশ

27

ইন SQL Server 2016+আপনি ব্যবহার করতে পারে STRING_SPLITফাংশন:

DECLARE @names NVARCHAR(MAX) = 'ruby,rails,scruffy,rubyonrails';

SELECT * 
FROM Tags
WHERE Name IN (SELECT [value] FROM STRING_SPLIT(@names, ','))
ORDER BY [Count] DESC;

বা:

DECLARE @names NVARCHAR(MAX) = 'ruby,rails,scruffy,rubyonrails';

SELECT t.*
FROM Tags t
JOIN STRING_SPLIT(@names,',')
  ON t.Name = [value]
ORDER BY [Count] DESC;

সরাসরি নমুনা

গৃহীত উত্তর অবশ্যই কাজের হবে এবং এটি পথে যেতে এক, কিন্তু এটা বিরোধী প্যাটার্ন।

E. মানগুলির তালিকা অনুসারে সারিগুলি সন্ধান করুন

এটি সাধারণ অ্যান্টি-প্যাটার্নের জন্য প্রতিস্থাপন যেমন অ্যাপ্লিকেশন স্তর বা লেনদেন-এসকিউএল-তে ডায়নামিক এসকিউএল স্ট্রিং তৈরি করা বা লাইক অপারেটর ব্যবহার করে:

SELECT ProductId, Name, Tags
FROM Product
WHERE ',1,2,3,' LIKE '%,' + CAST(ProductId AS VARCHAR(20)) + ',%';

সংযোজন :

STRING_SPLITসারণী ফাংশন সারি অনুমানের উন্নতি করতে , অস্থায়ী সারণী / সারণী ভেরিয়েবল হিসাবে বিভক্ত মানগুলিকে বাস্তবায়ন করা ভাল ধারণা:

DECLARE @names NVARCHAR(MAX) = 'ruby,rails,scruffy,rubyonrails,sql';

CREATE TABLE #t(val NVARCHAR(120));
INSERT INTO #t(val) SELECT s.[value] FROM STRING_SPLIT(@names, ',') s;

SELECT *
FROM Tags tg
JOIN #t t
  ON t.val = tg.TagName
ORDER BY [Count] DESC;

SedE - লাইভ ডেমো

সম্পর্কিত: সঞ্চিত পদ্ধতিতে মানগুলির একটি তালিকা কীভাবে পাস করবেন


মূল প্রশ্নের প্রয়োজনীয়তা রয়েছে SQL Server 2008। এই প্রশ্নটি প্রায়শই সদৃশ হিসাবে ব্যবহৃত হয়, তাই আমি এই উত্তরটি রেফারেন্স হিসাবে যুক্ত করেছি।


1
আমি এটি পরীক্ষা করে নিই, তবে আমার মনে হয় এটি সবচেয়ে পরিষ্কার 2016+ সমাধান। আমি এখনও চাই মাত্র একটি অ্যারে পাস করতে সক্ষম হতে চাই, তবে ততক্ষণ ...
ড্যানিয়েল

24

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

ALTER FUNCTION [dbo].[Fn_sqllist_to_table](@list  AS VARCHAR(8000),
                                           @delim AS VARCHAR(10))
RETURNS @listTable TABLE(
  Position INT,
  Value    VARCHAR(8000))
AS
  BEGIN
      DECLARE @myPos INT

      SET @myPos = 1

      WHILE Charindex(@delim, @list) > 0
        BEGIN
            INSERT INTO @listTable
                        (Position,Value)
            VALUES     (@myPos,LEFT(@list, Charindex(@delim, @list) - 1))

            SET @myPos = @myPos + 1

            IF Charindex(@delim, @list) = Len(@list)
              INSERT INTO @listTable
                          (Position,Value)
              VALUES     (@myPos,'')

            SET @list = RIGHT(@list, Len(@list) - Charindex(@delim, @list))
        END

      IF Len(@list) > 0
        INSERT INTO @listTable
                    (Position,Value)
        VALUES     (@myPos,@list)

      RETURN
  END 

তাই:

@Name varchar(8000) = null // parameter for search values    

select * from Tags 
where Name in (SELECT value From fn_sqllist_to_table(@Name,',')))
order by Count desc

20

এটি মোটামুটি, তবে আপনার কমপক্ষে একটি থাকার নিশ্চয়তা থাকলে আপনি এটি করতে পারেন:

SELECT ...
       ...
 WHERE tag IN( @tag1, ISNULL( @tag2, @tag1 ), ISNULL( @tag3, @tag1 ), etc. )

ইন ('ট্যাগ1', 'ট্যাগ 2', 'ট্যাগ 1', 'ট্যাগ1', 'ট্যাগ 1') এসকিউএল সার্ভারের মাধ্যমে সহজেই অনুকূলিত হয়ে যাবে। এছাড়াও, আপনি সরাসরি সূচক সন্ধান পান


1
নাল চেক সহ ptionচ্ছিক পরামিতিগুলি কার্যকারিতা নষ্ট করে দেয়, যেহেতু অপ্টিমাইজারটির দক্ষ অনুসন্ধান তৈরি করতে ব্যবহৃত প্যারামিটারগুলির সংখ্যা প্রয়োজন। 5 টি প্যারামিটারের প্রশ্নের জন্য 500 প্যারামিটারের চেয়ে পৃথক ক্যোয়ারী প্ল্যানের প্রয়োজন হতে পারে।
এরিক হার্ট

18

আমার মতে, এই সমস্যাটি সমাধানের সেরা উত্স, এই সাইটে পোস্ট করা হয়েছে:

Syscomments। দিনকার নেথি

CREATE FUNCTION dbo.fnParseArray (@Array VARCHAR(1000),@separator CHAR(1))
RETURNS @T Table (col1 varchar(50))
AS 
BEGIN
 --DECLARE @T Table (col1 varchar(50))  
 -- @Array is the array we wish to parse
 -- @Separator is the separator charactor such as a comma
 DECLARE @separator_position INT -- This is used to locate each separator character
 DECLARE @array_value VARCHAR(1000) -- this holds each array value as it is returned
 -- For my loop to work I need an extra separator at the end. I always look to the
 -- left of the separator character for each array value

 SET @array = @array + @separator

 -- Loop through the string searching for separtor characters
 WHILE PATINDEX('%' + @separator + '%', @array) <> 0 
 BEGIN
    -- patindex matches the a pattern against a string
    SELECT @separator_position = PATINDEX('%' + @separator + '%',@array)
    SELECT @array_value = LEFT(@array, @separator_position - 1)
    -- This is where you process the values passed.
    INSERT into @T VALUES (@array_value)    
    -- Replace this select statement with your processing
    -- @array_value holds the value of this element of the array
    -- This replaces what we just processed with and empty string
    SELECT @array = STUFF(@array, 1, @separator_position, '')
 END
 RETURN 
END

ব্যবহার করুন:

SELECT * FROM dbo.fnParseArray('a,b,c,d,e,f', ',')

ক্রেডিট ফর: দিনকার নেথি


প্রারম্ভিক সিএসভি কোনও টেবিলে পার্সিং (এক সময়, অল্প সংখ্যক উপাদান) ব্যতীত দুর্দান্ত উত্তর, পরিষ্কার এবং মডুলার, সুপার দ্রুত কার্যকরকরণ। যদিও প্যাটিনডেক্স () এর পরিবর্তে সরল / দ্রুত চারিনডেক্স () ব্যবহার করতে পারি? Charindex () আর্গুমেন্ট 'স্টার্ট_লোকেশন' কেও অনুমতি দেয় যা প্রতিটি ইটারের ইনপুট স্ট্রিং কাটা এড়াতে সক্ষম হতে পারে? মূল প্রশ্নের উত্তর দিতে কেবল ফাংশন ফলাফলের সাথে যোগ দিতে পারেন।
ক্রোকুসেক

18

আমি একটি টেবিল টাইপ প্যারামিটার পাস করবো (যেহেতু এটি এসকিউএল সার্ভার ২০০৮ ), এবং একটি where exists, বা অভ্যন্তরীণ জোড় করি। আপনি এক্সএমএল ব্যবহার করে sp_xml_preparedocument, এবং তারপরে সেই অস্থায়ী টেবিলটিকেও সূচক করতে পারেন।


পিএইচই এর উত্তরে বিল্ডিং টেম্প টেবিল রয়েছে (সিএসভি থেকে)।
ক্রোকুসেক

12

আইএমএইচও হ'ল সঠিক চরিত্রের স্ট্রিংয়ে তালিকাটি সংরক্ষণ করা (ডিবিএমএস সমর্থন করে দৈর্ঘ্যে সীমাবদ্ধ); কেবল কৌশলটি হল (প্রক্রিয়াকরণকে সহজ করার জন্য) আমার কাছে স্ট্রিংয়ের শুরুতে এবং শেষে পৃথক (আমার উদাহরণে একটি কমা) রয়েছে। ধারণাটি হ'ল "ফ্লাইকে স্বাভাবিক করুন", তালিকাকে এক-কলামের টেবিলের মধ্যে পরিণত করে যাতে প্রতিটি মান অনুযায়ী প্রতিটি সারি থাকে। এটি আপনাকে ঘুরিয়ে আনতে দেয়

ইন (সিটি 1, সিটি 2, সিটি 3 ... সিটিএন)

মধ্যে একটি

ইন (নির্বাচন করুন ...)

বা (আমি সম্ভবত সমাধানটি পছন্দ করব) একটি নিয়মিত যোগদান, যদি আপনি তালিকার সদৃশ মানগুলির সাথে সমস্যাগুলি এড়াতে কেবল "স্বতন্ত্র" যুক্ত হন।

দুর্ভাগ্যক্রমে, স্ট্রিং টুকরো করার কৌশলগুলি মোটামুটি পণ্য-নির্দিষ্ট। এখানে এসকিউএল সার্ভার সংস্করণ রয়েছে:

 with qry(n, names) as
       (select len(list.names) - len(replace(list.names, ',', '')) - 1 as n,
               substring(list.names, 2, len(list.names)) as names
        from (select ',Doc,Grumpy,Happy,Sneezy,Bashful,Sleepy,Dopey,' names) as list
        union all
        select (n - 1) as n,
               substring(names, 1 + charindex(',', names), len(names)) as names
        from qry
        where n > 1)
 select n, substring(names, 1, charindex(',', names) - 1) dwarf
 from qry;

ওরাকল সংস্করণ:

 select n, substr(name, 1, instr(name, ',') - 1) dwarf
 from (select n,
             substr(val, 1 + instr(val, ',', 1, n)) name
      from (select rownum as n,
                   list.val
            from  (select ',Doc,Grumpy,Happy,Sneezy,Bashful,Sleepy,Dopey,' val
                   from dual) list
            connect by level < length(list.val) -
                               length(replace(list.val, ',', ''))));

এবং মাইএসকিউএল সংস্করণ:

select pivot.n,
      substring_index(substring_index(list.val, ',', 1 + pivot.n), ',', -1) from (select 1 as n
     union all
     select 2 as n
     union all
     select 3 as n
     union all
     select 4 as n
     union all
     select 5 as n
     union all
     select 6 as n
     union all
     select 7 as n
     union all
     select 8 as n
     union all
     select 9 as n
     union all
     select 10 as n) pivot,    (select ',Doc,Grumpy,Happy,Sneezy,Bashful,Sleepy,Dopey,' val) as list where pivot.n <  length(list.val) -
                   length(replace(list.val, ',', ''));

(অবশ্যই, "পিভট" অবশ্যই সর্বাধিক সংখ্যক আইটেমের তালিকায় সন্ধান করতে হবে যতগুলি সারি ফিরতে হবে)


11

যদি আপনি এসকিউএল সার্ভার ২০০৮ বা তার পরে পেয়ে থাকেন তবে আমি একটি সারণী মূল্যবান প্যারামিটার ব্যবহার করব ।

আপনি যদি দুর্ভাগ্য হন তবে আটকে যাওয়ার পক্ষে যথেষ্ট এসকিউএল সার্ভার 2005 এ তবে আপনি এটির মতো একটি সিএলআর ফাংশন যুক্ত করতে পারেন ,

[SqlFunction(
    DataAccessKind.None,
    IsDeterministic = true,
    SystemDataAccess = SystemDataAccessKind.None,
    IsPrecise = true,
    FillRowMethodName = "SplitFillRow",
    TableDefinintion = "s NVARCHAR(MAX)"]
public static IEnumerable Split(SqlChars seperator, SqlString s)
{
    if (s.IsNull)
        return new string[0];

    return s.ToString().Split(seperator.Buffer);
}

public static void SplitFillRow(object row, out SqlString s)
{
    s = new SqlString(row.ToString());
}

যা আপনি এটির মতো ব্যবহার করতে পারেন,

declare @desiredTags nvarchar(MAX);
set @desiredTags = 'ruby,rails,scruffy,rubyonrails';

select * from Tags
where Name in [dbo].[Split] (',', @desiredTags)
order by Count desc

10

আমি মনে করি এটি একটি কেস যখন স্থির জিজ্ঞাসাটি কেবল যাওয়ার উপায় নয়। আপনার ধারাটিতে গতিশীলভাবে তালিকাটি তৈরি করুন, আপনার একক উদ্ধৃতিগুলি এড়িয়ে চলুন এবং গতিশীলভাবে এসকিউএল তৈরি করুন। এক্ষেত্রে আপনি সম্ভবত ছোট তালিকার কারণে কোনও পদ্ধতির সাথে খুব বেশি পার্থক্য দেখতে পাবেন না, তবে সবচেয়ে কার্যকর পদ্ধতিটি হ'ল এসকিউএলকে ঠিক আপনার পোস্টে যেমন পাঠানো হয় তেমন প্রেরণ করা। আমি মনে করি এটি সবচেয়ে কার্যকর পদ্ধতিতে লেখার পক্ষে একটি ভাল অভ্যাস যা প্রেটিস্ট কোডটি তৈরি করে না করে বা এসকিউএলকে গতিশীলভাবে গড়ে তোলার জন্য এটি খারাপ অভ্যাস হিসাবে বিবেচনা করে।

আমি দেখেছি যে বিভক্ত ফাংশনগুলি অনেকগুলি ক্ষেত্রে প্যারামিটারগুলি বড় হওয়ার ক্ষেত্রে ক্যোয়ারির চেয়ে বেশি কার্যকর হতে বেশি সময় নেয়। এসকিউএল ২০০৮-এ টেবিলের মূল্যবান পরামিতিগুলির সাথে সঞ্চিত পদ্ধতিটিই কেবলমাত্র অন্য বিকল্প হিসাবে আমি বিবেচনা করব, যদিও এটি সম্ভবত আপনার ক্ষেত্রে ধীর হবে। আপনি যদি টিভিপির প্রাথমিক কীটি সন্ধান করছেন তবে টিভিপি সম্ভবত বৃহত তালিকার জন্য দ্রুততর হবে, কারণ এসকিউএল যাইহোক তালিকাটির জন্য একটি অস্থায়ী টেবিল তৈরি করবে (তালিকাটি বড় হলে)। আপনি এটি পরীক্ষা না করা পর্যন্ত নিশ্চিতভাবে জানতে পারবেন না।

আমি নথের ডিফল্ট মান সহ 500 টি পরামিতি থাকা এবং কলাম 1 (যেখানে প্যারাম 1, @ প্যারাম 2, @ প্যারাম 3, ..., @ প্যারাম 500) রয়েছে সেগুলি আমিও দেখেছি also এটি এসকিউএলকে একটি টেম্প টেবিল তৈরি করতে, বাছাই / আলাদা করতে এবং তারপরে একটি সূচী সন্ধানের পরিবর্তে একটি টেবিল স্ক্যান করে। আপনি যে ক্যোয়ারীটিকে প্যারামিটারাইজেশন করে যাচ্ছেন তা মূলত এটিই হ'ল যদিও সামান্য পরিমাণে এটি কোনও লক্ষণীয় পার্থক্য তৈরি করবে না। আমি আপনার IN তালিকাগুলিতে NULL থাকার বিরুদ্ধে উচ্চ প্রস্তাব দিচ্ছি, যেন এটি একটি নোট-এ পরিবর্তিত হয় যা ইচ্ছা অনুযায়ী কাজ করবে না। আপনি গতিশীলভাবে প্যারামিটার তালিকাটি তৈরি করতে পারেন, তবে আপনি যে একমাত্র সুস্পষ্ট জিনিসটি অর্জন করবেন তা হ'ল অবজেক্টগুলি আপনার জন্য একক উদ্ধৃতিগুলি এড়িয়ে যাবে। পরামিতিগুলি অনুসন্ধান করার জন্য অবজেক্টগুলিকে ক্যোয়ারীটি পার্স করতে হবে বলে অ্যাপ্লিকেশন শেষের দিকেও এই পদ্ধতির সামান্য ধীর গতি রয়েছে।

সঞ্চিত পদ্ধতি বা প্যারামিটারাইজড কোয়েরিগুলির জন্য এক্সিকিউশন প্ল্যানগুলির পুনরায় ব্যবহার আপনাকে কার্যকারিতা অর্জন করতে পারে, তবে এটি কার্যকর করা প্রথম ক্যোয়ারির দ্বারা নির্ধারিত একটি কার্যকরকরণ পরিকল্পনায় আপনাকে লক করে রাখবে। এটি অনেক ক্ষেত্রে পরবর্তী প্রশ্নের জন্য আদর্শের চেয়ে কম হতে পারে। আপনার ক্ষেত্রে, এক্সিকিউশন পরিকল্পনাগুলির পুনঃব্যবহার সম্ভবত একটি প্লাস হতে পারে তবে উদাহরণটি সত্যই সহজ ক্যোয়ারী হওয়ায় এটি কোনও লাভ করতে পারে না।

ক্লিফস নোট:

আপনার ক্ষেত্রে যে কোনও কিছুই করা হোক না কেন, এটি তালিকার নির্দিষ্ট সংখ্যক আইটেমের সাথে প্যারামিটারাইজেশন হোক (যদি ব্যবহৃত না হয় তবে নথী হয়), প্যারামিটারগুলি দিয়ে বা ছাড়াই গতিশীলভাবে ক্যোয়ারী তৈরি করা বা টেবিলের মূল্যবান প্যারামিটারগুলির সাথে সঞ্চিত পদ্ধতি ব্যবহার করা কোনও তাত্পর্য সৃষ্টি করতে পারে না । তবে, আমার সাধারণ সুপারিশগুলি নিম্নরূপ:

আপনার কেস / কয়েকটি পরামিতি সহ সহজ প্রশ্ন:

গতিশীল এসকিউএল, যদি পরীক্ষাগুলি আরও ভাল পারফরম্যান্স দেখায় তবে পরামিতিগুলির সাথে।

পুনরায় ব্যবহারযোগ্য প্রয়োগের পরিকল্পনাগুলির সাথে অনুসন্ধানগুলি, কেবলমাত্র পরামিতিগুলি পরিবর্তন করে বা কোয়েরিটি জটিল হলে একাধিকবার বলা হয়:

গতিশীল পরামিতি সহ এসকিউএল।

বড় তালিকাসমূহের প্রশ্নগুলি:

টেবিলের মূল্যবান পরামিতিগুলির সাথে সঞ্চিত পদ্ধতি। তালিকাটি যদি বৃহত পরিমাণে পরিবর্তিত হয় তবে সঞ্চিত পদ্ধতিতে পুনরুদ্ধার করে ব্যবহার করুন বা প্রতিটি ক্যোয়ারীর জন্য একটি নতুন এক্সিকিউশন প্ল্যান উত্পন্ন করতে পরামিতি ছাড়াই গতিশীল এসকিউএল ব্যবহার করুন।


এখানে "সঞ্চিত পদ্ধতি" বলতে কী বোঝ? আপনি একটি উদাহরণ পোস্ট করতে পারেন?
struhtanov

9

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

    declare @x xml
    set @x='<items>
    <item myvalue="29790" />
    <item myvalue="31250" />
    </items>
    ';
    With CTE AS (
         SELECT 
            x.item.value('@myvalue[1]', 'decimal') AS myvalue
        FROM @x.nodes('//items/item') AS x(item) )

    select * from YourTable where tableColumnName in (select myvalue from cte)

1
CTEএবং @xকাটানো যেতে পারে / subselect মধ্যে inlined, যদি কাজ খুব সাবধানে করতে, যেমন দেখানো এই নিবন্ধটি
রবার্ট 4

9

আমি ডিফল্টরূপে একটি টেবিলের মূল্যবান ফাংশন (যা একটি স্ট্রিং থেকে একটি টেবিল ফেরত দেয়) IN শর্তে পৌঁছে দিয়ে চলেছি।

ইউডিএফের জন্য কোডটি এখানে (স্ট্যাক ওভারফ্লো থেকে কোথাও পেয়েছি, আমি এখনই উত্সটি খুঁজে পাচ্ছি না)

CREATE FUNCTION [dbo].[Split] (@sep char(1), @s varchar(8000))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT 
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces
  )

একবার আপনি এটি পেয়ে গেলে আপনার কোডটি এর মতো সহজ হবে:

select * from Tags 
where Name in (select s from dbo.split(';','ruby;rails;scruffy;rubyonrails'))
order by Count desc

আপনার যদি হাস্যকরভাবে দীর্ঘ স্ট্রিং না থাকে তবে এটি সারণী সূচকের সাথে ভালভাবে কাজ করা উচিত।

প্রয়োজনে আপনি এটি একটি টেম্প টেবিলের মধ্যে সন্নিবেশ করতে পারেন, এটি সূচী করুন, তারপরে একটি যোগদান চালান ...


8

আর একটি সম্ভাব্য সমাধান হ'ল সঞ্চিত পদ্ধতিতে পরিবর্তনশীল সংখ্যক তর্ক যুক্ত করার পরিবর্তে, আপনার পরে থাকা নামগুলি সম্বলিত একটি স্ট্রিং পাস করুন, তবে '<>' দিয়ে এগুলি ঘিরে তাদের অনন্য করুন। তারপরে নামগুলি খুঁজে পেতে PATINDEX ব্যবহার করুন:

SELECT * 
FROM Tags 
WHERE PATINDEX('%<' + Name + '>%','<jo>,<john>,<scruffy>,<rubyonrails>') > 0

8

নিম্নলিখিত সঞ্চিত পদ্ধতি ব্যবহার করুন। এটি একটি কাস্টম বিভক্ত ফাংশন ব্যবহার করে, যা এখানে পাওয়া যাবে

 create stored procedure GetSearchMachingTagNames 
    @PipeDelimitedTagNames varchar(max), 
    @delimiter char(1) 
    as  
    begin
         select * from Tags 
         where Name in (select data from [dbo].[Split](@PipeDelimitedTagNames,@delimiter) 
    end

8

যদি আমরা কমানার (,) সীমানাঙ্কিত আইএন ক্লজের ভিতরে স্ট্রিংগুলি সঞ্চয় করে রাখি, আমরা মানগুলি পেতে Charindex ফাংশনটি ব্যবহার করতে পারি। আপনি যদি নেট ব্যবহার করেন, তবে আপনি স্কেলপ্যারামিটার দিয়ে মানচিত্র করতে পারেন।

ডিডিএল লিপি:

CREATE TABLE Tags
    ([ID] int, [Name] varchar(20))
;

INSERT INTO Tags
    ([ID], [Name])
VALUES
    (1, 'ruby'),
    (2, 'rails'),
    (3, 'scruffy'),
    (4, 'rubyonrails')
;

টি-এসকিউএল:

DECLARE @Param nvarchar(max)

SET @Param = 'ruby,rails,scruffy,rubyonrails'

SELECT * FROM Tags
WHERE CharIndex(Name,@Param)>0

আপনি উপরের বিবৃতিটি আপনার .NET কোডে ব্যবহার করতে পারেন এবং স্কেলপ্যারামিটার দিয়ে প্যারামিটারটি মানচিত্র করতে পারেন।

ফিডলারের ডেমো

সম্পাদনা: নীচের স্ক্রিপ্টটি ব্যবহার করে SelectedTags নামে সারণী তৈরি করুন।

ডিডিএল লিপি:

Create table SelectedTags
(Name nvarchar(20));

INSERT INTO SelectedTags values ('ruby'),('rails')

টি-এসকিউএল:

DECLARE @list nvarchar(max)
SELECT @list=coalesce(@list+',','')+st.Name FROM SelectedTags st

SELECT * FROM Tags
WHERE CharIndex(Name,@Param)>0

আপনি যেখানে এই সম্ভাব্য মানগুলির একটি হার্ড-কোডেড তালিকা নেই সেখানে এই কাজের একটি উদাহরণ দেখাতে পারেন?
জন স্যান্ডার্স

@ জনসন্ডার্স, আমি কোনও হার্ডকডযুক্ত তালিকা ব্যবহার না করে স্ক্রিপ্টটি সম্পাদনা করেছি। যাচাই করুন.
Gaudhaman008

3
এই বিকল্পের সাথে একটি সীমাবদ্ধতা। স্ট্রিংটি পাওয়া গেলে CharIndex 1 প্রদান করে। আইএন একটি শর্তাবলী জন্য একটি ম্যাচ ফেরত। "স্ট্যাক" এর জন্য চারআইডেক্স একটি শব্দ "স্ট্যাকওভারফ্লো" IN এর জন্য 1 প্রদান করবে। উপরে PatIndex ব্যবহার করে এই উত্তরে একটি সামান্য টুইট রয়েছে যা এই সীমাবদ্ধতা কাটিয়ে উঠেছে এমন '<'% নাম% '> দিয়ে নামগুলি আবদ্ধ করে। যদিও এই সমস্যার সৃজনশীল সমাধান।
রিচার্ড ভিভিয়ান

7

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


7

ইন ColdFusion আমরা শুধু একটি করুন:

<cfset myvalues = "ruby|rails|scruffy|rubyonrails">
    <cfquery name="q">
        select * from sometable where values in <cfqueryparam value="#myvalues#" list="true">
    </cfquery>

7

এখানে একটি কৌশল যা কোয়েরি স্ট্রিংয়ের জন্য স্থানীয় টেবিলটি পুনরায় তৈরি করে। এটি এইভাবে করা সমস্ত পার্সিং সমস্যা দূর করে।

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

ব্যবহারকারীর সংজ্ঞায়িত প্রকারের ব্যবহার alচ্ছিক। প্রকারটি তৈরি করা কেবল একবার তৈরি করা হয় এবং সময়ের আগে করা যায়। অন্যথায় স্ট্রিংয়ের ঘোষণায় একটি পূর্ণ টেবিল প্রকার যুক্ত করুন।

সাধারণ প্যাটার্নটি প্রসারিত করা সহজ এবং আরও জটিল টেবিলগুলি পাস করার জন্য ব্যবহার করা যেতে পারে।

-- Create a user defined type for the list.
CREATE TYPE [dbo].[StringList] AS TABLE(
    [StringValue] [nvarchar](max) NOT NULL
)

-- Create a sample list using the list table type.
DECLARE @list [dbo].[StringList]; 
INSERT INTO @list VALUES ('one'), ('two'), ('three'), ('four')

-- Build a string in which we recreate the list so we can pass it to exec
-- This can be done in any language since we're just building a string.
DECLARE @str nvarchar(max);
SET @str = 'DECLARE @list [dbo].[StringList]; INSERT INTO @list VALUES '

-- Add all the values we want to the string. This would be a loop in C++.
SELECT @str = @str + '(''' + StringValue + '''),' FROM @list

-- Remove the trailing comma so the query is valid sql.
SET @str = substring(@str, 1, len(@str)-1)

-- Add a select to test the string.
SET @str = @str + '; SELECT * FROM @list;'

-- Execute the string and see we've pass the table correctly.
EXEC(@str)

7

এসকিউএল সার্ভার 2016+ এ অন্য সম্ভাবনাটি ব্যবহার করা OPENJSON ফাংশনটি ।

এই পদ্ধতিটি ওপেনজেসনে ব্লগ করা হয়েছে - আইডির তালিকা অনুসারে সারিগুলি নির্বাচন করার অন্যতম সেরা উপায় ways

নীচে একটি সম্পূর্ণ কাজের উদাহরণ

CREATE TABLE dbo.Tags
  (
     Name  VARCHAR(50),
     Count INT
  )

INSERT INTO dbo.Tags
VALUES      ('VB',982), ('ruby',1306), ('rails',1478), ('scruffy',1), ('C#',1784)

GO

CREATE PROC dbo.SomeProc
@Tags VARCHAR(MAX)
AS
SELECT T.*
FROM   dbo.Tags T
WHERE  T.Name IN (SELECT J.Value COLLATE Latin1_General_CI_AS
                  FROM   OPENJSON(CONCAT('[', @Tags, ']')) J)
ORDER  BY T.Count DESC

GO

EXEC dbo.SomeProc @Tags = '"ruby","rails","scruffy","rubyonrails"'

DROP TABLE dbo.Tags 

7

এখানে অন্য বিকল্প। সঞ্চিত পদ্ধতিতে স্ট্রিং প্যারামিটার হিসাবে কেবল কমা-সীমাবদ্ধ তালিকাটি পাস করুন এবং:

CREATE PROCEDURE [dbo].[sp_myproc]
    @UnitList varchar(MAX) = '1,2,3'
AS
select column from table
where ph.UnitID in (select * from CsvToInt(@UnitList))

এবং ফাংশন:

CREATE Function [dbo].[CsvToInt] ( @Array varchar(MAX))
returns @IntTable table
(IntValue int)
AS
begin
    declare @separator char(1)
    set @separator = ','
    declare @separator_position int
    declare @array_value varchar(MAX)

    set @array = @array + ','

    while patindex('%,%' , @array) <> 0
    begin

        select @separator_position = patindex('%,%' , @array)
        select @array_value = left(@array, @separator_position - 1)

        Insert @IntTable
        Values (Cast(@array_value as int))
        select @array = stuff(@array, 1, @separator_position, '')
    end
    return
end

6

আমার কাছে একটি উত্তর আছে যার কোনও ইউডিএফ প্রয়োজন হয় না, এক্সএমএল কারণ IN একটি নির্বাচনী বিবৃতি গ্রহণ করে যেমন পরীক্ষা থেকে পরীক্ষা করুন যেখানে ডেটা ইন (টেবিলের মান নির্বাচন করুন)

স্ট্রিংটিকে টেবিলের মধ্যে রূপান্তর করার জন্য আপনার কেবল সত্যই প্রয়োজন need

এটি একটি পুনরাবৃত্ত সিটিই, বা একটি সংখ্যা টেবিল (বা মাস্টার..সেস্প_মূল্য) দিয়ে একটি কোয়েরি দিয়ে করা যেতে পারে

এখানে সিটিই সংস্করণ।

DECLARE @InputString varchar(8000) = 'ruby,rails,scruffy,rubyonrails'

SELECT @InputString = @InputString + ','

;WITH RecursiveCSV(x,y) 
AS 
(
    SELECT 
        x = SUBSTRING(@InputString,0,CHARINDEX(',',@InputString,0)),
        y = SUBSTRING(@InputString,CHARINDEX(',',@InputString,0)+1,LEN(@InputString))
    UNION ALL
    SELECT 
        x = SUBSTRING(y,0,CHARINDEX(',',y,0)),
        y = SUBSTRING(y,CHARINDEX(',',y,0)+1,LEN(y))
    FROM 
        RecursiveCSV 
    WHERE
        SUBSTRING(y,CHARINDEX(',',y,0)+1,LEN(y)) <> '' OR 
        SUBSTRING(y,0,CHARINDEX(',',y,0)) <> ''
)
SELECT
    * 
FROM 
    Tags
WHERE 
    Name IN (select x FROM RecursiveCSV)
OPTION (MAXRECURSION 32767);

6

আমি শীর্ষে ভোট দেওয়া উত্তরের আরও সংক্ষিপ্ত সংস্করণ ব্যবহার করেছি :

List<SqlParameter> parameters = tags.Select((s, i) => new SqlParameter("@tag" + i.ToString(), SqlDbType.NVarChar(50)) { Value = s}).ToList();

var whereCondition = string.Format("tags in ({0})", String.Join(",",parameters.Select(s => s.ParameterName)));

এটি ট্যাগ পরামিতিগুলির মাধ্যমে দু'বার লুপ করে; তবে বেশিরভাগ সময় এটি বিবেচনা করে না (এটি আপনার বাধা হয়ে দাঁড়াবে না; যদি তা হয় তবে লুপটি আনলোল করুন)।

আপনি যদি পারফরম্যান্সে সত্যিই আগ্রহী হন এবং দুবার লুপের মাধ্যমে পুনরাবৃত্তি করতে চান না, তবে এখানে একটি সুন্দর সংস্করণ দেওয়া হয়েছে:

var parameters = new List<SqlParameter>();
var paramNames = new List<string>();
for (var i = 0; i < tags.Length; i++)  
{
    var paramName = "@tag" + i;

    //Include size and set value explicitly (not AddWithValue)
    //Because SQL Server may use an implicit conversion if it doesn't know
    //the actual size.
    var p = new SqlParameter(paramName, SqlDbType.NVarChar(50) { Value = tags[i]; } 
    paramNames.Add(paramName);
    parameters.Add(p);
}

var inClause = string.Join(",", paramNames);

5

এই সমস্যার আরেকটি উত্তর এখানে।

(6/4/13 এ নতুন সংস্করণ পোস্ট করা হয়েছে)।

    private static DataSet GetDataSet(SqlConnectionStringBuilder scsb, string strSql, params object[] pars)
    {
        var ds = new DataSet();
        using (var sqlConn = new SqlConnection(scsb.ConnectionString))
        {
            var sqlParameters = new List<SqlParameter>();
            var replacementStrings = new Dictionary<string, string>();
            if (pars != null)
            {
                for (int i = 0; i < pars.Length; i++)
                {
                    if (pars[i] is IEnumerable<object>)
                    {
                        List<object> enumerable = (pars[i] as IEnumerable<object>).ToList();
                        replacementStrings.Add("@" + i, String.Join(",", enumerable.Select((value, pos) => String.Format("@_{0}_{1}", i, pos))));
                        sqlParameters.AddRange(enumerable.Select((value, pos) => new SqlParameter(String.Format("@_{0}_{1}", i, pos), value ?? DBNull.Value)).ToArray());
                    }
                    else
                    {
                        sqlParameters.Add(new SqlParameter(String.Format("@{0}", i), pars[i] ?? DBNull.Value));
                    }
                }
            }
            strSql = replacementStrings.Aggregate(strSql, (current, replacementString) => current.Replace(replacementString.Key, replacementString.Value));
            using (var sqlCommand = new SqlCommand(strSql, sqlConn))
            {
                if (pars != null)
                {
                    sqlCommand.Parameters.AddRange(sqlParameters.ToArray());
                }
                else
                {
                    //Fail-safe, just in case a user intends to pass a single null parameter
                    sqlCommand.Parameters.Add(new SqlParameter("@0", DBNull.Value));
                }
                using (var sqlDataAdapter = new SqlDataAdapter(sqlCommand))
                {
                    sqlDataAdapter.Fill(ds);
                }
            }
        }
        return ds;
    }

চিয়ার্স।


4

একমাত্র বিজয়ী পদক্ষেপ না খেলাই।

আপনার জন্য কোনও অসীম পরিবর্তনশীলতা নেই। কেবল সীমাবদ্ধ পরিবর্তনশীলতা।

এসকিউএল-তে আপনার এর মতো একটি ধারা রয়েছে:

and ( {1}==0 or b.CompanyId in ({2},{3},{4},{5},{6}) )

সি # কোডে আপনি এরকম কিছু করেন:

  int origCount = idList.Count;
  if (origCount > 5) {
    throw new Exception("You may only specify up to five originators to filter on.");
  }
  while (idList.Count < 5) { idList.Add(-1); }  // -1 is an impossible value
  return ExecuteQuery<PublishDate>(getValuesInListSQL, 
               origCount,   
               idList[0], idList[1], idList[2], idList[3], idList[4]);

সুতরাং মূলত যদি গণনা 0 হয় তবে কোনও ফিল্টার নেই এবং সমস্ত কিছু দিয়ে যায়। যদি গণনা 0 এর চেয়ে বেশি হয় তবে মানটি তালিকায় অবশ্যই থাকা উচিত, তবে তালিকাটি অসম্ভব মান সহ পাঁচটি করে দেওয়া হয়েছে (যাতে এসকিউএল এখনও বোঝায়)

কখনও কখনও খোঁড়া দ্রবণটিই কেবল বাস্তবে কাজ করে।

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