2009-06-21 22 views
9

मैं एक एमएस SQL ​​सर्वर 2005 डेटाबेस में डेटा डालने के लिए एक कंसोल अनुप्रयोग पर काम कर रहा हूं। मेरे पास डालने के लिए वस्तुओं की एक सूची है। यहाँ मैं उदाहरण के रूप में कर्मचारी वर्ग का उपयोग करें:एसक्यूएल एक पंक्ति या एकाधिक पंक्ति डेटा डालें?

foreach (Employee item in employees) 
{ 
    string sql = @"INSERT INTO Mytable (id, name, salary) 
    values ('@id', '@name', '@salary')"; 
    // replace @par with values 
    cmd.CommandText = sql; // cmd is IDbCommand 
    cmd.ExecuteNonQuery(); 
} 

या मैं इस तरह की एक मेंड डालने क्वेरी निर्माण कर सकते हैं:

List<Employee> employees; 

मैं क्या कर सकते हैं इस तरह समय में एक ऑब्जेक्ट सम्मिलित करने के लिए है

string sql = @"INSERT INTO MyTable (id, name, salary) "; 
int count = employees.Count; 
int index = 0; 
foreach (Employee item in employees) 
{ 
    sql = sql + string.format(
    "SELECT {0}, '{1}', {2} ", 
    item.ID, item.Name, item.Salary); 
    if (index != (count-1)) 
     sql = sql + " UNION ALL "; 
    index++ 
} 
cmd.CommandType = sql; 
cmd.ExecuteNonQuery(); 

मुझे लगता है कि बाद का मामला एक बार में डेटा की पंक्तियों को सम्मिलित करने जा रहा है। हालांकि, अगर मेरे पास डेटा के कई केएस हैं, तो SQL क्वेरी स्ट्रिंग के लिए कोई सीमा है?

मुझे यकीन नहीं है कि प्रदर्शन के संदर्भ में डेटा की एक पंक्ति के साथ एकाधिक पंक्तियों में से एक डालने से बेहतर है या नहीं?

इसे बेहतर तरीके से करने के लिए कोई सुझाव?

उत्तर

14

दरअसल, जिस तरह से आपने लिखा है, आपका पहला विकल्प तेज़ होगा।

  1. आपके दूसरे उदाहरण में इसमें कोई समस्या है। आप sql = + sql + आदि कर रहे हैं। यह लूप के प्रत्येक पुनरावृत्ति के लिए एक नई स्ट्रिंग ऑब्जेक्ट बनाने के लिए जा रहा है। (स्ट्रिंगबिल्डर वर्ग देखें)। तकनीकी रूप से, आप पहले उदाहरण में भी एक नई स्ट्रिंग ऑब्जेक्ट बनाने जा रहे हैं, लेकिन अंतर यह है कि इसे पिछले स्ट्रिंग विकल्प से सभी जानकारी कॉपी करने की आवश्यकता नहीं है।

  2. जिस तरह से आपने इसे स्थापित किया है, एसक्यूएल सर्वर को आखिरकार एक बड़े पैमाने पर पूछताछ का मूल्यांकन करना होगा जब आप आखिरकार इसे भेज दें जो निश्चित रूप से कुछ समय ले रहा है कि यह क्या करना है। मुझे यह कहना चाहिए कि यह इस बात पर निर्भर है कि आपको कितनी बड़ी संख्या में आवेषण करने की आवश्यकता है। यदि एन छोटा है, तो आप शायद ठीक होने जा रहे हैं, लेकिन जैसे ही यह आपकी समस्या बढ़ता है, केवल खराब हो जाएगा।

थोक आवेषण अलग-अलग करने के लिए कैसे एसक्यूएल सर्वर बैच लेनदेन संभालती वजह से लोगों की तुलना में तेजी है। यदि आप सी # से डेटा सम्मिलित करने जा रहे हैं तो आपको पहला दृष्टिकोण लेना चाहिए और रैप में प्रत्येक 500 आवेषण कहें और इसे प्रतिबद्ध करें, फिर अगले 500 और इसी तरह से करें। इसका लाभ यह भी है कि यदि कोई बैच विफल रहता है, तो आप उनको जाल कर सकते हैं और पता लगा सकते हैं कि क्या गलत हुआ और केवल उनको दोबारा डालें। ऐसा करने के अन्य तरीके हैं, लेकिन यह निश्चित रूप से प्रदान किए गए दो उदाहरणों में सुधार होगा।

var iCounter = 0; 
foreach (Employee item in employees) 
{ 

    if (iCounter == 0) 
    { 
    cmd.BeginTransaction; 
    } 
    string sql = @"INSERT INTO Mytable (id, name, salary) 
    values ('@id', '@name', '@salary')"; 
    // replace @par with values 
    cmd.CommandText = sql; // cmd is IDbCommand 
    cmd.ExecuteNonQuery(); 
    iCounter ++; 
    if(iCounter >= 500) 
    { 
    cmd.CommitTransaction; 
    iCounter = 0; 
    } 
} 

if(iCounter > 0) 
    cmd.CommitTransaction; 
+0

आईएनईआरटी एसक्यूएल के बजाय एसपी को कॉल करने के बारे में कैसे? एसपी समान पैरामीटर लेगा, लेकिन एसपी के भीतर प्रत्येक कॉल के लिए प्रतिबद्ध है। क्या एसपी कॉल में से कोई भी विफल होने पर लेनदेन वापस ले जाया जाएगा? –

+0

@ केविन, इंटेलिजेंस में CommitTransaction क्यों नहीं दिखता है? – uSeRnAmEhAhAhAhAhA

+0

सच में, मुझे नहीं पता। मुझे नीचे ट्रैक करना होगा क्यों @Spike – kemiller2002

0

this thread, पर मैंने तालिका मूल्यवान पैरामीटर के बारे में उत्तर दिया है।

0

Bulk-copy आमतौर पर अपने आप से सम्मिलित करने से तेज़ होता है।

यदि आप अभी भी इसे अपने सुझाए गए तरीकों में से एक में करना चाहते हैं तो आपको इसे बनाना चाहिए ताकि आप आसानी से सर्वर पर भेजे गए प्रश्नों का आकार बदल सकें। इस तरह आप बाद में अपने उत्पादन वातावरण में गति के लिए अनुकूलित कर सकते हैं। क्वेरी आकार के आधार पर क्वेरी समय v ary alot हो सकता है।

0

SQL सर्वर क्वेरी के लिए बैच आकार 65,536 * नेटवर्क पैकेट आकार होने पर सूचीबद्ध है। नेटवर्क पैकेट आकार डिफ़ॉल्ट रूप से 4kbs है लेकिन बदला जा सकता है। दायरे प्राप्त करने के लिए एसक्यूएल 2008 के लिए Maximum capacity articl ई देखें। एसक्यूएल 2005 में भी एक ही सीमा है।

3

एमएस एसक्यूएल सर्वर 2008 आप

CREATE TYPE MyUdt AS TABLE (Id int, Name nvarchar(50), salary int) 

तो नेट टेबल UDT कि अपनी मेज शामिल होंगे बना सकते हैं, तो आप अपने संग्रहित प्रक्रियाओं और करने के लिए अपने с # -code में इस UDT उपयोग कर सकते हैं बैच-आवेषण। सपा:

CREATE PROCEDURE uspInsert 
(@MyTvp AS MyTable READONLY) 
AS 
    INSERT INTO [MyTable] 
     SELECT * FROM @MyTvp 

सी # (कल्पना करो कि रिकॉर्ड आप डेटासेट डी एस की तालिका में पहले से ही निहित डालने के लिए "MyTable" की जरूरत है):

using(conn) 
{ 
    SqlCommand cmd = new SqlCommand("uspInsert", conn); 
    cmd.CommandType = CommandType.StoredProcedure; 

    SqlParameter myParam = cmd.Parameters.AddWithValue 
    ("@MyTvp", ds.Tables["MyTable"]); 

    myParam.SqlDbType = SqlDbType.Structured; 
    myParam.TypeName = "dbo.MyUdt"; 

    // Execute the stored procedure 
    cmd.ExecuteNonQuery(); 
} 

तो, यह समाधान है।

अंततः मैं आपको अपने जैसे कोड का उपयोग करने से रोकना चाहता हूं (तारों का निर्माण करना और फिर इस स्ट्रिंग को निष्पादित करना), क्योंकि निष्पादन का यह तरीका SQL-इंजेक्शन के लिए उपयोग किया जा सकता है।

संबंधित मुद्दे