সি # এসকিউএল সার্ভার - একটি সঞ্চিত পদ্ধতিতে একটি তালিকা পাস করা


111

আমি আমার সি # কোড থেকে একটি এসকিউএল সার্ভার সঞ্চিত পদ্ধতি কল করছি:

using (SqlConnection conn = new SqlConnection(connstring))
{
   conn.Open();
   using (SqlCommand cmd = new SqlCommand("InsertQuerySPROC", conn))
   {
      cmd.CommandType = CommandType.StoredProcedure;

      var STableParameter = cmd.Parameters.AddWithValue("@QueryTable", QueryTable);
      var NDistanceParameter = cmd.Parameters.AddWithValue("@NDistanceThreshold", NDistanceThreshold);
      var RDistanceParameter = cmd.Parameters.AddWithValue(@"RDistanceThreshold", RDistanceThreshold);

      STableParameter .SqlDbType = SqlDbType.Structured;
      NDistanceParameter.SqlDbType = SqlDbType.Int;
      RDistanceParameter.SqlDbType = SqlDbType.Int;

      // Execute the query
      SqlDataReader QueryReader = cmd.ExecuteReader();

আমার সঞ্চিত প্রোক মোটামুটি মানসম্পন্ন তবে এটিতে একটি সংযুক্তি রয়েছে QueryTable(সুতরাং একটি সঞ্চিত প্রোক ব্যবহারের জন্য প্রয়োজনীয়তা)।

এখন: আমি List<string>প্যারামিটার সেটে স্ট্রিংগুলির একটি তালিকা যুক্ত করতে চাই । উদাহরণস্বরূপ, আমার সঞ্চিত প্রোক কোয়েরিটি এরকম হয়:

SELECT feature 
FROM table1 t1 
INNER JOIN @QueryTable t2 ON t1.fid = t2.fid 
WHERE title IN <LIST_OF_STRINGS_GOES_HERE>

তবে স্ট্রিংগুলির তালিকাটি গতিশীল এবং কয়েকশো দীর্ঘ।

List<string>স্টোরেড প্রোকে স্ট্রিংয়ের একটি তালিকা দেওয়ার কি কোনও উপায় আছে ??? অথবা এটি করার আরও ভাল উপায় আছে?

অনেক ধন্যবাদ, ব্রেট


সম্ভবত, এর প্রতিলিপি stackoverflow.com/questions/209686/...
আন্দ্রে Agibalov

এসকিউএল সার্ভারের কোন সংস্করণ ?? 2005 ?? 2008 ?? 2008 আর 2 ?? এসকিউএল সার্ভার ২০০৮ এবং আরও নতুনটির "টেবিলের মূল্যবান প্যারামিটার" ধারণা রয়েছে (বিশদগুলির জন্য রেডথের প্রতিক্রিয়া দেখুন)
মার্ক_স

অসম্পর্কিত টিপ: SqlDataReader এছাড়াও IDisposable তাই একটি মধ্যে হওয়া উচিত usingব্লক।
রিচার্ডিসিমো

উত্তর:


178

আপনি যদি এসকিউএল সার্ভার ২০০৮ ব্যবহার করে থাকেন তবে একটি নতুন বৈশিষ্ট্যযুক্ত যা একটি ব্যবহারকারী সংজ্ঞায়িত সারণী প্রকার বলে। এটি কীভাবে ব্যবহার করা যায় তার একটি উদাহরণ এখানে দেওয়া হয়েছে:

আপনার ব্যবহারকারী সংজ্ঞায়িত সারণীর প্রকার তৈরি করুন:

CREATE TYPE [dbo].[StringList] AS TABLE(
    [Item] [NVARCHAR](MAX) NULL
);

এর পরে আপনার এটি আপনার সঞ্চিত পদ্ধতিতে সঠিকভাবে ব্যবহার করতে হবে:

CREATE PROCEDURE [dbo].[sp_UseStringList]
    @list StringList READONLY
AS
BEGIN
    -- Just return the items we passed in
    SELECT l.Item FROM @list l;
END

অবশেষে এটি সি # তে ব্যবহার করার জন্য কয়েকটি স্কয়ার রয়েছে:

using (var con = new SqlConnection(connstring))
{
    con.Open();

    using (SqlCommand cmd = new SqlCommand("exec sp_UseStringList @list", con))
    {
        using (var table = new DataTable()) {
          table.Columns.Add("Item", typeof(string));

          for (int i = 0; i < 10; i++)
            table.Rows.Add("Item " + i.ToString());

          var pList = new SqlParameter("@list", SqlDbType.Structured);
          pList.TypeName = "dbo.StringList";
          pList.Value = table;

          cmd.Parameters.Add(pList);

          using (var dr = cmd.ExecuteReader())
          {
            while (dr.Read())
                Console.WriteLine(dr["Item"].ToString());
          }
         }
    }
}

এসএসএমএস থেকে এটি কার্যকর করা

DECLARE @list AS StringList

INSERT INTO @list VALUES ('Apple')
INSERT INTO @list VALUES ('Banana')
INSERT INTO @list VALUES ('Orange')

-- Alternatively, you can populate @list with an INSERT-SELECT
INSERT INTO @list
   SELECT Name FROM Fruits

EXEC sp_UseStringList @list

10
প্যারামিটারটির মান নির্ধারণের জন্য এটি কি ডেটাটেবল সংজ্ঞায়িত করতে হবে? অন্য কোন হালকা পদ্ধতির?
ca9163d9

2
আমরা এটি চেষ্টা করেছি কিন্তু আমরা দেখতে পেয়েছি যে এর অসুবিধা এনিটি ফ্রেমওয়ার্ক দ্বারা সমর্থিত নয়
হানা

7
আপনি যদি লিংক 2 এসকিউএল ব্যবহার করেন তবে এই সমাধানের সাথে যত্নবান হন, যেমন এটি ব্যবহারকারী হিসাবে নির্ধারিত টেবিল প্রকারকে সমর্থন করে না !!! কমা বিচ্ছিন্ন তালিকা এবং পার্সার ফাংশন ব্যবহার করে জোন রায়নের উত্তরে একটি কার্যকারিতা পাওয়া যাবে, তবে
এতেও

3
এই ক্ষেত্রে @ ফাজি, লিনক 2 এসকিউএল ব্যবহার করবেন না। টি-এসকিউএলে স্ট্রিং
কনটেনটেশন এবং পার্সিংয়ের পক্ষে এটি ভাল

2
হ্যাঁ, সুতরাং আপনি কীভাবে এটি এসএসএমএস থেকে বাস্তবায়িত করবেন?
সিনায়েস্টিক

21

এই পরিস্থিতিতে সাধারণ প্যাটার্নটি হ'ল কমা সীমানাঙ্কিত তালিকার উপাদানগুলিকে পাস করা এবং তারপরে এসকিউএল বিভাজনে যে টেবিলটি আপনি ব্যবহার করতে পারেন তা। বেশিরভাগ লোকেরা সাধারণত এটির জন্য একটি নির্দিষ্ট ফাংশন তৈরি করে:

 INSERT INTO <SomeTempTable>
 SELECT item FROM dbo.SplitCommaString(@myParameter)

এবং তারপরে আপনি এটিকে অন্যান্য প্রশ্নের ক্ষেত্রে ব্যবহার করতে পারেন।


17
সম্পূর্ণরূপে একটি ডিবিও.স্প্লিটকম স্ট্রিং বাস্তবায়নের জন্য আমাকে একটি লিঙ্ক ফেলতে দাও: goo.gl/P9ROs
ভেলি জেব্রেভ

3
এবং যখন আপনার কোনও ডেটা ফিল্ডে কমা থাকে তখন কী ঘটে?
কেভিন পানকো

3
পরিবর্তে পাইপ দিয়ে এটি সীমাবদ্ধ।
প্যারিসে অ্যালেক্স

@ অ্যালেক্সইনপ্যারিস আপনার ডেটা ক্ষেত্রগুলির একটিতে যদি পাইপ থাকে তবে কী হবে?
রায়লভলেস

2
তারপরে এমন কিছু ব্যবহার করুন যা আপনার ডেটা ক্ষেত্রগুলিতে নেই। আপনার ডেটা পরিষ্কার করুন, যদি প্রয়োজন হয় তবে বেশি ডেটা না আমি কখনও দেখেছি পাইপ ব্যবহার করেছি। যদি তারা একেবারে প্রয়োজনীয় হয় তবে some বা § এর মতো আরও কিছু চরিত্র সন্ধান করুন §
প্যারিসে অ্যালেক্স

9

না, অ্যারে / তালিকাগুলি সরাসরি এসকিউএল সার্ভারে দেওয়া যায় না।

নিম্নলিখিত বিকল্পগুলি উপলব্ধ:

  1. কমা-বিস্মৃত তালিকাটি পাস করা এবং তারপরে এসকিউএল-তে কোনও ফাংশন থাকার ফলে তালিকাটি বিভক্ত হয়। কমা বিস্মৃত তালিকাটি সম্ভবত এনভারচর () হিসাবে পাস করা হবে
  2. এক্সএমএল পাস করুন এবং এসকিউএল সার্ভারে একটি ফাংশন রয়েছে তালিকার প্রতিটি মানের জন্য এক্সএমএলকে পার্স করুন
  3. নতুন সংজ্ঞায়িত ব্যবহারকারী সংজ্ঞায়িত সারণী প্রকার (এসকিউএল ২০০ 2008) ব্যবহার করুন
  4. গতিশীলভাবে এসকিউএল তৈরি করুন এবং কাঁচা তালিকায় "1,2,3,4" হিসাবে পাস করুন এবং এসকিউএল স্টেটমেন্টটি তৈরি করুন। এটি এসকিউএল ইনজেকশন আক্রমণে ঝুঁকিপূর্ণ তবে এটি কাজ করবে।

2

হ্যাঁ, স্টোরড প্রোক প্যারামিটারটিকে হিসাবে তৈরি করুন VARCHAR(...) এবং তারপরে কমা দ্বারা পৃথক করা মানগুলি একটি সঞ্চিত পদ্ধতিতে পাস করুন।

আপনি যদি এসকিএল সার্ভার ২০০৮ ব্যবহার করে থাকেন তবে আপনি টিভিপি ( টেবিলের মান প্যারামিটার ) লাভ করতে পারেন : এসকিউএল ২০০ TV টিভিপি এবং লিনকিউ যদি স্ট্রিংয়ের অ্যারের চেয়ে কোয়েরি টেবিলের কাঠামো আরও জটিল হয় তবে এটি একটি ওভারকিল হবে কারণ এসকিউএল সার্ভারের মধ্যে টেবিলের প্রকারটি তৈরি করা দরকার


2

তালিকার পরিবর্তে একটি কলাম দিয়ে একটি ডেটাবেল তৈরি করুন এবং টেবিলের সাথে স্ট্রিং যুক্ত করুন। আপনি এই ডেটেবলকে কাঠামোগত ধরণের হিসাবে পাস করতে পারেন এবং আপনার টেবিলের শিরোনাম ক্ষেত্রের সাথে আরও একটি যোগদান করতে পারেন।


এটাই যাওয়ার পথ। আমি আসলে ডিবি সাইডে একটি টেবিল তৈরি করেছি এবং সার্ভারে বিসিপি রাইট দিয়ে লোড করেছি।
dier

1

আপনি যদি এসকিউএল-তে কোনও সিএসভি তালিকা বিভক্ত করতে পছন্দ করেন তবে সাধারণ টেবিল এক্সপ্রেশন (সিটিই) ব্যবহার করে এটি করার আলাদা উপায় রয়েছে । সিটিই ব্যবহার করে স্ট্রিং বিভক্ত করার দক্ষ উপায় দেখুন ।


ধন্যবাদ। পরিবর্তে একটি স্ট্যাক ওভারফ্লো প্রশ্নে পরিবর্তিত হয়েছে।
ল্যারি সিলভারম্যান

0

কেবলমাত্র আমি যে সম্পর্কে সচেতন তা হ'ল CSV তালিকা তৈরি করা এবং তারপরে স্ট্রিং হিসাবে পাস করা। তারপরে, এসপি দিকে, কেবল এটি ভাগ করুন এবং আপনার যা প্রয়োজন তা করুন।


0
CREATE TYPE [dbo].[StringList1] AS TABLE(
[Item] [NVARCHAR](MAX) NULL,
[counts][nvarchar](20) NULL);

টেবিল হিসাবে একটি টিওয়াইপি তৈরি করুন এবং এটি "স্ট্রিংলিস্ট 1" হিসাবে নাম দিন

create PROCEDURE [dbo].[sp_UseStringList1]
@list StringList1 READONLY
AS
BEGIN
    -- Just return the items we passed in
    SELECT l.item,l.counts FROM @list l;
    SELECT l.item,l.counts into tempTable FROM @list l;
 End

উপরের মতো একটি পদ্ধতি তৈরি করুন এবং এটিকে "ইউজারস্ট্রিংলিস্ট 1" এর নাম দিন

String strConnection = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString.ToString();
            SqlConnection con = new SqlConnection(strConnection);
            con.Open();
            var table = new DataTable();

            table.Columns.Add("Item", typeof(string));
            table.Columns.Add("count", typeof(string));

            for (int i = 0; i < 10; i++)
            {
                table.Rows.Add(i.ToString(), (i+i).ToString());

            }
                SqlCommand cmd = new SqlCommand("exec sp_UseStringList1 @list", con);


                    var pList = new SqlParameter("@list", SqlDbType.Structured);
                    pList.TypeName = "dbo.StringList1";
                    pList.Value = table;

                    cmd.Parameters.Add(pList);
                    string result = string.Empty;
                    string counts = string.Empty;
                    var dr = cmd.ExecuteReader();

                    while (dr.Read())
                    {
                        result += dr["Item"].ToString();
                        counts += dr["counts"].ToString();
                    }

সি # এ চেষ্টা করুন

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