সঞ্চিত পদ্ধতিতে অ্যারে প্যারামিটারগুলি পাস করা


53

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

প্রস্তাব # 1 - সারণী মূল্যবান পরামিতি। আমি একটি টেবিল টাইপ ডাব্লু / কেবল একটি আইডি ক্ষেত্র সংজ্ঞায়িত করতে পারি এবং আপডেট করতে আইডি পূর্ণ টেবিলটি প্রেরণ করতে পারি।

প্রস্তাব # 2 - প্রোএম বডিতে ওপেনএক্সএমএল () সহ এক্সএমএল প্যারামিটার (বারচর)।

প্রস্তাব # 3 - তালিকা পার্সিং। আমি বরং এটি এড়ানো চাই, যদি সম্ভব হয় তবে এটি অযৌক্তিক এবং ত্রুটিযুক্ত বলে মনে হয়।

এগুলির মধ্যে কোনও পছন্দ, বা কোনও ধারণা আমি মিস করেছি?


আপনি কীভাবে আইডির বড় তালিকা পাচ্ছেন?
ল্যারি কোলম্যান

আমি অন্য সঞ্চিত প্রকল্পের মাধ্যমে "পে-লোড" ডেটার সাথে তাদের নীচে টেনে আনছি। আমার সমস্ত ডেটা আপডেট করার দরকার নেই, যদিও - নির্দিষ্ট রেকর্ডে কেবল একটি পতাকা আপডেট করুন।
ডি ল্যামবার্ট

উত্তর:


42

এই বিষয়ে সেরা নিবন্ধগুলি এরল্যান্ড সোমমারস্কোগের লিখেছেন:

তিনি সমস্ত বিকল্পগুলি কভার করেন এবং বেশ ভাল ব্যাখ্যা করেন।

উত্তরের সংক্ষিপ্ততার জন্য দুঃখিত, তবে অ্যারেঞ্জ সম্পর্কিত এরল্যান্ডের নিবন্ধটি গাছ এবং অন্যান্য এসকিউএল ট্রিট সম্পর্কিত জো সেলকো বইয়ের মতো :)


23

স্ট্যাকওভারফ্লোতে এটির একটি দুর্দান্ত আলোচনা রয়েছে যা অনেকগুলি পদ্ধতির অন্তর্ভুক্ত করে। এসকিউএল সার্ভার ২০০+ এর জন্য আমি যেটিকে পছন্দ করি তা হ'ল টেবিল-মূল্যবান পরামিতি ব্যবহার করা । এটি আপনার সমস্যার মূলত এসকিউএল সার্ভারের সমাধান - সঞ্চিত পদ্ধতিতে মানগুলির তালিকায় পাস করা।

এই পদ্ধতির সুবিধা হ'ল:

  • আপনার সমস্ত ডেটা 1 প্যারামিটার হিসাবে পাস করে একটি সঞ্চিত পদ্ধতি কল করুন
  • টেবিল ইনপুট কাঠামোগত এবং দৃ strongly়ভাবে টাইপ করা হয়
  • কোনও স্ট্রিম বিল্ডিং / পার্সিং বা এক্সএমএল হ্যান্ডলিং নেই
  • ফিল্টার করতে, যোগদান করতে বা যেকোনো কিছুতে সহজেই টেবিল ইনপুট ব্যবহার করতে পারে

তবে, খেয়াল করুন: আপনি যদি এমন কোনও স্টোরেজ পদ্ধতি কল করেন যা ADO.NET বা ODBC এর মাধ্যমে টিভিপি ব্যবহার করে এবং এসকিউএল সার্ভার প্রোফাইলারটির সাথে ক্রিয়াকলাপটি একবার দেখুন, আপনি লক্ষ্য করবেন যে এসকিউএল সার্ভারটি প্রতিটি সারির জন্য একটিINSERT করে টিভিপি লোড করার জন্য বেশ কয়েকটি বিবৃতি পেয়েছে টিভিপিতে , তারপরে প্রক্রিয়া কল করার পরে। এটি নকশা দ্বারা । এই ব্যাচের INSERTএস প্রক্রিয়াটি প্রতিবারই সংকলিত হওয়া দরকার এবং একটি ছোট ওভারহেড গঠন করে। যাইহোক, এমনকি এই ওভারহেড থাকা সত্ত্বেও, টিভিপিগুলি এখনও বেশিরভাগ ব্যবহারের ক্ষেত্রে কর্মক্ষমতা এবং ব্যবহারযোগ্যতার দিক থেকে অন্যান্য পদ্ধতিকে দূরে সরিয়ে দেয়।

আপনি যদি আরও জানতে চান, এরল্যান্ড سومমারস্কোগের টেবিল-মূল্যবান পরামিতিগুলি কীভাবে কাজ করে এবং তার জন্য বেশ কয়েকটি উদাহরণ সরবরাহ করে তার সম্পূর্ণ চর্মসার রয়েছে।

আমি আরও একটি উদাহরণ এখানে দিয়েছি:

CREATE TYPE id_list AS TABLE (
    id int NOT NULL PRIMARY KEY
);
GO

CREATE PROCEDURE [dbo].[tvp_test] (
      @param1           INT
    , @customer_list    id_list READONLY
)
AS
BEGIN
    SELECT @param1 AS param1;

    -- join, filter, do whatever you want with this table 
    -- (other than modify it)
    SELECT *
    FROM @customer_list;
END;
GO

DECLARE @customer_list id_list;

INSERT INTO @customer_list (
    id
)
VALUES (1), (2), (3), (4), (5), (6), (7);

EXECUTE [dbo].[tvp_test]
      @param1 = 5
    , @customer_list = @customer_list
;
GO

DROP PROCEDURE dbo.tvp_test;
DROP TYPE id_list;
GO

আমি এটি চালানোর সময় আমার একটি ত্রুটি পাওয়া যায়: এমএসজি 2715, স্তর 16, রাজ্য 3, প্রক্রিয়া টিভিপি_স্টেস্ট, লাইন 4 [ব্যাচ শুরু লাইন 4] কলাম, প্যারামিটার বা ভেরিয়েবল # 2: ডেটা টাইপ আইডি_লিস্টটি খুঁজে পাওয়া যায় না। প্যারামিটার বা ভেরিয়েবল '@ কাস্টোমার_লিস্ট' এর একটি অবৈধ ডেটা টাইপ রয়েছে। এমএসজি 1087, স্তর 16, রাজ্য 1, প্রক্রিয়া টিভিপি_স্টেস্ট, লাইন 13 [ব্যাচ শুরুর লাইন 4] অবশ্যই টেবিলের পরিবর্তনশীল "@ কাস্টমারের_ তালিকা" ঘোষণা করতে হবে।
দামিয়ান

@ দামিয়ান - CREATE TYPEশুরুতে বিবৃতিটি কি সফলভাবে চালানো হয়েছিল? আপনি এসকিউএল সার্ভারের কোন সংস্করণটি চালাচ্ছেন?
নিক চ্যামাস

এসপি কোডটিতে আপনার এই বাক্যটি ইনলাইন রয়েছে `SELECT @ param1 AS param1; ' । উদ্দেশ্য কি? আপনি ব্যবহার বা প্যারাম 1 ব্যবহার করেন না তাই কেন আপনি এটিকে এসপি শিরোনামে প্যারামিটার হিসাবে রেখেছিলেন?
ইমেজ

@ ইয়েজ - এটি কেবল একটি স্বেচ্ছাসেবী উদাহরণ ছিল। কথাটি @customer_listনয় @param1। উদাহরণটি সহজভাবে দেখায় যে আপনি বিভিন্ন প্যারামিটারের প্রকারগুলি মিশ্রিত করতে পারেন।
নিক চাম্মাস

21

সমগ্র বিষয়ের উপর আলোচনা করা হয় Erland Sommarskog ডেফিনিটিভ নিবন্ধ: "অ্যারেগুলির এবং SQL সার্ভার মধ্যে তালিকা" । কোন সংস্করণ চয়ন করবেন তা চয়ন করুন।

সংক্ষিপ্তসার, এসকিউএল সার্ভার ২০০৮-এর পূর্ববর্তী ক্ষেত্রে যেখানে টিভিপিরা বাকী লোকদের ট্রাম্প করে

  • সিএসভি, আপনার পছন্দগুলি ভাগ করুন (আমি সাধারণত একটি নম্বর টেবিল ব্যবহার করি)
  • এক্সএমএল এবং পার্স (এসকিউএল সার্ভার 2005+ এর সাথে আরও ভাল)
  • ক্লায়েন্টের উপর একটি অস্থায়ী টেবিল তৈরি করুন

অন্যান্য কৌশল এবং চিন্তাভাবনাটি দেখার জন্য নিবন্ধটি যাইহোক পড়ার মতো।

সম্পাদনা: অন্য কোথাও বিশাল তালিকার দেরী উত্তর : সঞ্চিত পদ্ধতিতে অ্যারে প্যারামিটারগুলি পাস করা


14

আমি জানি যে আমি এই দলের জন্য দেরি করেছি, তবে অতীতে আমার এ জাতীয় সমস্যা হয়েছিল, 100 কে বিগিন্ট নম্বর পাঠাতে হয়েছিল এবং কয়েকটি মানদণ্ড করেছি did আমরা একটি চিত্র হিসাবে তাদের বাইনারি ফর্ম্যাটে প্রেরণ শেষ করেছি - এটি 100 কে সংখ্যা পর্যন্ত অন্য কিছুর চেয়ে দ্রুত ছিল।

এখানে আমার পুরানো (এসকিউএল সার্ভার 2005) কোডটি রয়েছে:

SELECT  Number * 8 + 1 AS StartFrom ,
        Number * 8 + 8 AS MaxLen
INTO    dbo.ParsingNumbers
FROM    dbo.Numbers
GO

CREATE FUNCTION dbo.ParseImageIntoBIGINTs ( @BIGINTs IMAGE )
RETURNS TABLE
AS RETURN
    ( SELECT    CAST(SUBSTRING(@BIGINTs, StartFrom, 8) AS BIGINT) Num
      FROM      dbo.ParsingNumbers
      WHERE     MaxLen <= DATALENGTH(@BIGINTs)
    )
GO

নিম্নলিখিত কোডটি একটি বাইনারি ব্লবতে পূর্ণসংখ্যার প্যাকিং করছে। আমি এখানে বাইটের ক্রমটি বিপরীত করছি:

static byte[] UlongsToBytes(ulong[] ulongs)
{
int ifrom = ulongs.GetLowerBound(0);
int ito   = ulongs.GetUpperBound(0);
int l = (ito - ifrom + 1)*8;
byte[] ret = new byte[l];
int retind = 0;
for(int i=ifrom; i<=ito; i++)
{
ulong v = ulongs[i];
ret[retind++] = (byte) (v >> 0x38);
ret[retind++] = (byte) (v >> 0x30);
ret[retind++] = (byte) (v >> 40);
ret[retind++] = (byte) (v >> 0x20);
ret[retind++] = (byte) (v >> 0x18);
ret[retind++] = (byte) (v >> 0x10);
ret[retind++] = (byte) (v >> 8);
ret[retind++] = (byte) v;
}
return ret;
}

9

আপনাকে এসও হিসাবে উল্লেখ করা বা এখানে এটির উত্তর দেওয়ার মধ্যে আমি ছিন্ন হয়ে পড়েছি, 'কারণ এটি প্রায় একটি প্রোগ্রামিং প্রশ্ন। তবে যেহেতু আমি ইতিমধ্যে আমার কাছে একটি সমাধান পেয়েছি ... আমি এটি পোস্ট করব;)

এইটি যেভাবে কাজ করে তা হ'ল আপনি কোনও কমা সীমাবদ্ধ স্ট্রিং (সরল বিভাজন, সিএসভি স্টাইল বিভাজন করেন না) ভ্যারিচার (4000) হিসাবে সঞ্চিত পদ্ধতিতে খাওয়ান এবং তারপরে সেই তালিকাটি এই ফাংশনে ফিড করুন এবং একটি সহজ টেবিলটি ফিরে পাবেন, শুধু বারচারের একটি টেবিল।

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

পর্যায়ক্রমে আপনি একটি সিএলআর ডেটা টেবিলের সাহায্যে কিছু করতে পারেন এবং এতে ফিড দিতে পারেন তবে এটি সমর্থন করার জন্য আরও কিছুটা ওভারহেড এবং প্রত্যেকে সিএসভি তালিকা বুঝতে পারে।

USE [Database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[splitListToTable] (@list      nvarchar(MAX), @delimiter nchar(1) = N',')
      RETURNS @tbl TABLE (value     varchar(4000)      NOT NULL) AS
/*
http://www.sommarskog.se/arrays-in-sql.html
This guy is apparently THE guy in SQL arrays and lists 

Need an easy non-dynamic way to split a list of strings on input for comparisons

Usage like thus:

DECLARE @sqlParam VARCHAR(MAX)
SET @sqlParam = 'a,b,c'

SELECT * FROM (

select 'a' as col1, '1' as col2 UNION
select 'a' as col1, '2' as col2 UNION
select 'b' as col1, '3' as col2 UNION
select 'b' as col1, '4' as col2 UNION
select 'c' as col1, '5' as col2 UNION
select 'c' as col1, '6' as col2 ) x 
WHERE EXISTS( SELECT value FROM splitListToTable(@sqlParam,',') WHERE x.col1 = value )

*/
BEGIN
   DECLARE @endpos   int,
           @startpos int,
           @textpos  int,
           @chunklen smallint,
           @tmpstr   nvarchar(4000),
           @leftover nvarchar(4000),
           @tmpval   nvarchar(4000)

   SET @textpos = 1
   SET @leftover = ''
   WHILE @textpos <= datalength(@list) / 2
   BEGIN
      SET @chunklen = 4000 - datalength(@leftover) / 2
      SET @tmpstr = @leftover + substring(@list, @textpos, @chunklen)
      SET @textpos = @textpos + @chunklen

      SET @startpos = 0
      SET @endpos = charindex(@delimiter, @tmpstr)

      WHILE @endpos > 0
      BEGIN
         SET @tmpval = ltrim(rtrim(substring(@tmpstr, @startpos + 1,
                                             @endpos - @startpos - 1)))
         INSERT @tbl (value) VALUES(@tmpval)
         SET @startpos = @endpos
         SET @endpos = charindex(@delimiter, @tmpstr, @startpos + 1)
      END

      SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
   END

   INSERT @tbl(value) VALUES (ltrim(rtrim(@leftover)))
   RETURN
END

ঠিক আছে, আমি বিশেষত কমা-বিস্মৃত তালিকাটি এড়ানোর চেষ্টা করছিলাম যাতে আমাকে এরকম কিছু লিখতে হবে না, তবে এটি ইতিমধ্যে লেখা হয়ে গেছে, আমি অনুমান করি যে সমাধানটি আমি আবার মিশ্রণে ফেলে দিতে পারি। ;-)
ডি ল্যামবার্ট

1
আমি বললাম চেষ্টা করা এবং সত্যটি সবচেয়ে সহজ। আপনি কোডের সেকেন্ডে সি # তে কমা দ্বারা বিচ্ছিন্ন তালিকাটি ছুঁড়ে ফেলতে পারেন এবং আপনি এটিকে এই ফাংশনটিতে (এটি আপনার স্প্রোকের মধ্যে আসার পরে) খুব তাড়াতাড়ি টস করতে পারেন এবং আপনাকে এ সম্পর্কে খুব চিন্তা করতে হবে না। I এবং আমি জানি আপনি বলেছেন যে আপনি কোনও ফাংশন ব্যবহার করতে চান না, তবে আমি মনে করি এটি সবচেয়ে সহজ উপায় (সম্ভবত সবচেয়ে কার্যকর নয়)
jcolebrand

5

আমি নিয়মিতভাবে বিভিন্ন এসকিউএল সার্ভারের সঞ্চিত পদ্ধতি দ্বারা প্রক্রিয়াজাত করতে আমাদের অ্যাপ্লিকেশন থেকে প্রেরিত সারিগুলির 100 টি এবং 10000 সারিগুলির সেটগুলি নিয়মিত পেয়েছি।

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

আমি এক্সএমএল প্রসেসিং বিবেচনা করিনি কারণ আমি কোনও এক্সএমএল বাস্তবায়ন পাইনি যা 10,000 এর বেশি "সারি" দিয়ে পারফরম্যান্ট থাকে।

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

এসকিউএল সার্ভার প্রসেসিং সম্পর্কিত সমস্ত পছন্দের মতো আপনার ব্যবহারের মডেলের উপর ভিত্তি করে আপনার পছন্দ নির্বাচন করতে হবে।


5

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

এছাড়াও নোট করুন: আমি একটি পরিষেবার জন্য কিছু কোড লিখছি, এবং আমি অন্যান্য শ্রেণিতে প্রচুর পূর্বনির্ধারিত কোড কোড পেয়েছি, তবে আমি এটি কনসোল অ্যাপ্লিকেশন হিসাবে লিখছি যাতে আমি এটি ডিবাগ করতে পারি, তাই আমি এগুলি থেকে সমস্ত ছিঁড়ে ফেলেছি কনসোল অ্যাপ্লিকেশন আমার কোডিং শৈলীটি (হার্ডকডযুক্ত সংযোগের স্ট্রিংয়ের মতো) ক্ষমা করুন কারণ এটি "ছুঁড়ে ফেলার জন্য বিল্ড করুন" এর মতো ছিল। আমি কীভাবে একটি ব্যবহার করি তা প্রদর্শন করতে List<customObject>এবং টেবিলে সহজেই এটি ডাটাবেসে ঠেলাতে চেয়েছিলাম , যা আমি সঞ্চিত পদ্ধতিতে ব্যবহার করতে পারি। সি # এবং টিএসকিউএল কোড নীচে:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using a;

namespace a.EventAMI {
    class Db {
        private static SqlCommand SqlCommandFactory(string sprocName, SqlConnection con) { return new SqlCommand { CommandType = CommandType.StoredProcedure, CommandText = sprocName, CommandTimeout = 0, Connection = con }; }

        public static void Update(List<Current> currents) {
            const string CONSTR = @"just a hardwired connection string while I'm debugging";
            SqlConnection con = new SqlConnection( CONSTR );

            SqlCommand cmd = SqlCommandFactory( "sprocname", con );
            cmd.Parameters.Add( "@CurrentTVP", SqlDbType.Structured ).Value = Converter.GetDataTableFromIEnumerable( currents, typeof( Current ) ); //my custom converter class

            try {
                using ( con ) {
                    con.Open();
                    cmd.ExecuteNonQuery();
                }
            } catch ( Exception ex ) {
                ErrHandler.WriteXML( ex );
                throw;
            }
        }
    }
    class Current {
        public string Identifier { get; set; }
        public string OffTime { get; set; }
        public DateTime Off() {
            return Convert.ToDateTime( OffTime );
        }

        private static SqlCommand SqlCommandFactory(string sprocName, SqlConnection con) { return new SqlCommand { CommandType = CommandType.StoredProcedure, CommandText = sprocName, CommandTimeout = 0, Connection = con }; }

        public static List<Current> GetAll() {
            List<Current> l = new List<Current>();

            const string CONSTR = @"just a hardcoded connection string while I'm debugging";
            SqlConnection con = new SqlConnection( CONSTR );

            SqlCommand cmd = SqlCommandFactory( "sprocname", con );

            try {
                using ( con ) {
                    con.Open();
                    using ( SqlDataReader reader = cmd.ExecuteReader() ) {
                        while ( reader.Read() ) {
                            l.Add(
                                new Current {
                                    Identifier = reader[0].ToString(),
                                    OffTime = reader[1].ToString()
                                } );
                        }
                    }

                }
            } catch ( Exception ex ) {
                ErrHandler.WriteXML( ex );
                throw;
            }

            return l;
        }
    }
}

-------------------
the converter class
-------------------
using System;
using System.Collections;
using System.Data;
using System.Reflection;

namespace a {
    public static class Converter {
        public static DataTable GetDataTableFromIEnumerable(IEnumerable aIEnumerable) {
            return GetDataTableFromIEnumerable( aIEnumerable, null );
        }

        public static DataTable GetDataTableFromIEnumerable(IEnumerable aIEnumerable, Type baseType) {
            DataTable returnTable = new DataTable();

            if ( aIEnumerable != null ) {
                //Creates the table structure looping in the in the first element of the list
                object baseObj = null;

                Type objectType;

                if ( baseType == null ) {
                    foreach ( object obj in aIEnumerable ) {
                        baseObj = obj;
                        break;
                    }

                    objectType = baseObj.GetType();
                } else {
                    objectType = baseType;
                }

                PropertyInfo[] properties = objectType.GetProperties();

                DataColumn col;

                foreach ( PropertyInfo property in properties ) {
                    col = new DataColumn { ColumnName = property.Name };
                    if ( property.PropertyType == typeof( DateTime? ) ) {
                        col.DataType = typeof( DateTime );
                    } else if ( property.PropertyType == typeof( Int32? ) ) {
                        col.DataType = typeof( Int32 );
                    } else {
                        col.DataType = property.PropertyType;
                    }
                    returnTable.Columns.Add( col );
                }

                //Adds the rows to the table

                foreach ( object objItem in aIEnumerable ) {
                    DataRow row = returnTable.NewRow();

                    foreach ( PropertyInfo property in properties ) {
                        Object value = property.GetValue( objItem, null );
                        if ( value != null )
                            row[property.Name] = value;
                        else
                            row[property.Name] = "";
                    }

                    returnTable.Rows.Add( row );
                }
            }
            return returnTable;
        }

    }
}

USE [Database]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROC [dbo].[Event_Update]
    @EventCurrentTVP    Event_CurrentTVP    READONLY
AS

/****************************************************************
    author  cbrand
    date    
    descrip I'll ask you to forgive me the anonymization I've made here, but hope this helps
    caller  such and thus application
****************************************************************/

BEGIN TRAN Event_Update

DECLARE @DEBUG INT

SET @DEBUG = 0 /* test using @DEBUG <> 0 */

/*
    Replace the list of outstanding entries that are still currently disconnected with the list from the file
    This means remove all existing entries (faster to truncate and insert than to delete on a join and insert, yes?)
*/
TRUNCATE TABLE [database].[dbo].[Event_Current]

INSERT INTO [database].[dbo].[Event_Current]
           ([Identifier]
            ,[OffTime])
SELECT [Identifier]
      ,[OffTime]
  FROM @EventCurrentTVP

IF (@@ERROR <> 0 OR @DEBUG <> 0) 
BEGIN
ROLLBACK TRAN Event_Update
END
ELSE
BEGIN
COMMIT TRAN Event_Update
END

USE [Database]
GO

CREATE TYPE [dbo].[Event_CurrentTVP] AS TABLE(
    [Identifier] [varchar](20) NULL,
    [OffTime] [datetime] NULL
)
GO

এছাড়াও, আমি আমার কোডিং শৈলীতে গঠনমূলক সমালোচনা করব যদি আপনার কাছে এমন অফার থাকে তবে (এই প্রশ্নটি উপস্থিত সমস্ত পাঠকের কাছে) তবে দয়া করে এটি গঠনমূলক রাখুন;) ... আপনি যদি সত্যিই আমাকে চান তবে আমাকে এখানে চ্যাটরুমে সন্ধান করুন । আশা করি এই সংখ্যার কোডের সাথে কেউ দেখতে পাবে যে তারা List<Current>ডিবিতে একটি টেবিল List<T>এবং তাদের অ্যাপ্লিকেশনটিতে একটি টেবিল হিসাবে সংজ্ঞায়িত করেছে সেগুলি তারা কীভাবে ব্যবহার করতে পারে ।


3

আমি হয় প্রস্তাব # 1 নিয়ে যাব বা বিকল্প হিসাবে, একটি স্ক্র্যাচ টেবিল তৈরি করব যা কেবলমাত্র প্রসেসড আইডি রাখে। প্রসেসিংয়ের সময় সেই টেবিলটিতে Inোকান, তারপরে একবার শেষ হয়ে গেলে নীচের মতো একটি প্রোকে কল করুন:

BEGIN TRAN

UPDATE dt
SET processed = 1
FROM dataTable dt
JOIN processedIds pi ON pi.id = dt.id;

TRUNCATE TABLE processedIds

COMMIT TRAN

আপনি অনেকগুলি সন্নিবেশ করান, তবে সেগুলি একটি ছোট টেবিলে থাকবে তাই এটি দ্রুত হওয়া উচিত। আপনি ADO.net বা আপনি যে কোনও ডেটা অ্যাডাপ্টার ব্যবহার করছেন তা ব্যবহার করে আপনার সন্নিবেশগুলিতে ব্যাচ করতে পারে।


2

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

ট্যাগগুলির দ্বারা বর্ণিত স্কেল-সার্ভার -2008 এর প্রসঙ্গে E. সোমমারস্কোগ অ্যারে এবং এসকিউএল সার্ভার ২০০৮-এর তালিকাসমূহের একটি আরও দুর্দান্ত নিবন্ধ রয়েছে । বিটিডাব্লু আমি মারিয়ানের তার উত্তরে উল্লেখ করা নিবন্ধে এটি পেয়েছি।

কেবল লিঙ্কটি দেওয়ার পরিবর্তে, আমি এর লিখিত সামগ্রীর তালিকাটি উদ্ধৃত করেছি:

  • ভূমিকা
  • পটভূমি
  • টি-এসকিউএলে সারণী-মূল্যবান পরামিতি
  • ADO .NET থেকে সারণী-মূল্যবান পরামিতিগুলি পাস করা
    • একটি তালিকা ব্যবহার করে
    • একটি ডেটা টেবিল ব্যবহার করে
    • একটি ডেটা রিডার ব্যবহার করে
    • চূড়ান্ত মন্তব্য
  • অন্যান্য এপিআই থেকে সারণী-মূল্যবান পরামিতি ব্যবহার করা
    • ODBC
    • OLE DB
    • ADO
    • লিনকিউ এবং সত্তা ফ্রেমওয়ার্ক
    • JDBC এর
    • পিএইচপি
    • পার্ল
    • আপনার এপিআই যদি টিভিপিগুলিকে সমর্থন না করে তবে কী হবে
  • পারফরম্যান্স বিবেচনা
    • সার্ভার-সাইড
    • মক্কেলের পক্ষে
    • প্রাইমারি কী না?
  • স্বীকৃতি এবং প্রতিক্রিয়া
  • পরিবর্ধন ও পরিবর্তন তালিকা

সেখানে উল্লিখিত কৌশলগুলির বাইরে, আমার অনুভূতি আছে যে কিছু ক্ষেত্রে বাল্ককপি এবং বাল্ক সন্নিবেশ সাধারণ ক্ষেত্রে উল্লেখ করার যোগ্যতা রাখে।


1

সঞ্চিত পদ্ধতিতে অ্যারে প্যারামিটারগুলি পাস করা

এমএস এসকিউএল 2016 এর সর্বশেষতম সংস্করণে

এমএস এসকিউএল ২০১ With এর সাথে তারা একটি নতুন ফাংশন প্রবর্তন করেছে: একাধিক মানকে বিশ্লেষণ করতে SPLIT_STRING ()

এটি আপনার সমস্যাটিকে সহজেই সমাধান করতে পারে।

এমএস এসকিউএল ওল্ড সংস্করণে

আপনি যদি পুরানো সংস্করণ ব্যবহার করেন তবে এই পদক্ষেপটি অনুসরণ করুন:

প্রথমে একটি ফাংশন করুন:

 ALTER FUNCTION [dbo].[UDF_IDListToTable]
 (
    @list          [varchar](MAX),
    @Seperator     CHAR(1)
  )
 RETURNS @tbl TABLE (ID INT)
 WITH 

 EXECUTE AS CALLER
 AS
  BEGIN
    DECLARE @position INT
    DECLARE @NewLine CHAR(2) 
    DECLARE @no INT
    SET @NewLine = CHAR(13) + CHAR(10)

    IF CHARINDEX(@Seperator, @list) = 0
    BEGIN
    INSERT INTO @tbl
    VALUES
      (
        @list
      )
END
ELSE
BEGIN
    SET @position = 1
    SET @list = @list + @Seperator
    WHILE CHARINDEX(@Seperator, @list, @position) <> 0
    BEGIN
        SELECT @no = SUBSTRING(
                   @list,
                   @position,
                   CHARINDEX(@Seperator, @list, @position) - @position
               )

        IF @no <> ''
            INSERT INTO @tbl
            VALUES
              (
                @no
              )

        SET @position = CHARINDEX(@Seperator, @list, @position) + 1
    END
END
RETURN
END

এটি তৈরির পরে, কেবল আপনার স্ট্রিংটি বিভাজক সহ এই ফাংশনে প্রেরণ করুন।

আমি আশা করি এটি আপনার পক্ষে সহায়ক। :-)


-1

"টাইপ টেবিল তৈরি করুন" তৈরি করতে এটি ব্যবহার করুন। ব্যবহারকারীর জন্য সহজ উদাহরণ

CREATE TYPE unit_list AS TABLE (
    ItemUnitId int,
    Amount float,
    IsPrimaryUnit bit
);

GO
 CREATE TYPE specification_list AS TABLE (
     ItemSpecificationMasterId int,
    ItemSpecificationMasterValue varchar(255)
);

GO
 declare @units unit_list;
 insert into @units (ItemUnitId, Amount, IsPrimaryUnit) 
  values(12,10.50, false), 120,100.50, false), (1200,500.50, true);

 declare @spec specification_list;
  insert into @spec (ItemSpecificationMasterId,temSpecificationMasterValue) 
   values (12,'test'), (124,'testing value');

 exec sp_add_item "mytests", false, @units, @spec


//Procedure definition
CREATE PROCEDURE sp_add_item
(   
    @Name nvarchar(50),
    @IsProduct bit=false,
    @UnitsArray unit_list READONLY,
    @SpecificationsArray specification_list READONLY
)
AS


BEGIN
    SET NOCOUNT OFF     

    print @Name;
    print @IsProduct;       
    select * from @UnitsArray;
    select * from @SpecificationsArray;
END
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.