SSMS
 sql >> डेटाबेस >  >> Database Tools >> SSMS

SSMS SMO ऑब्जेक्ट:क्वेरी परिणाम प्राप्त करें

सबसे आसान बात यह है कि ExecuteNonQuery . के लिए आपको जो नंबर वापस मिलता है, उसे प्रिंट कर लें :

int rowsAffected = server.ConnectionContext.ExecuteNonQuery(/* ... */);
if (rowsAffected != -1)
{
     Console.WriteLine("{0} rows affected.", rowsAffected);
}

यह काम करना चाहिए, लेकिन SET NOCOUNT . का सम्मान नहीं करेगा वर्तमान सत्र/दायरे की सेटिंग।

अन्यथा आप ऐसा करेंगे जैसे आप "सादे" ADO.NET के साथ करेंगे। ServerConnection.ExecuteNonQuery() . का उपयोग न करें विधि, लेकिन एक SqlCommand बनाएं अंतर्निहित SqlConnection . तक पहुंच कर वस्तु वस्तु। उस पर StatementCompleted . की सदस्यता लें घटना।

using (SqlCommand command = server.ConnectionContext.SqlConnectionObject.CreateCommand())
{
    // Set other properties for "command", like StatementText, etc.

    command.StatementCompleted += (s, e) => {
         Console.WriteLine("{0} row(s) affected.", e.RecordCount);
    };

    command.ExecuteNonQuery();
}

StatementCompleted का उपयोग करना (इसके बजाय, मान लें, मैन्युअल रूप से उस मान को प्रिंट करना जो ExecuteNonQuery() . है रिटर्न) का यह लाभ है कि यह बिल्कुल SSMS या SQLCMD की तरह काम करता है। EXE होगा:

  • उन आदेशों के लिए जिनके पास ROWCOUNT नहीं है, उन्हें बिल्कुल भी नहीं कहा जाएगा (उदा. GO, USE)।
  • यदि SET NOCOUNT ON सेट किया गया था, इसे बिल्कुल भी नहीं बुलाया जाएगा।
  • अगर SET NOCOUNT OFF सेट किया गया था, इसे बैच के अंदर हर स्टेटमेंट के लिए बुलाया जाएगा।

(साइडबार:ऐसा लगता है कि StatementCompleted जब DONE_IN_PROC . के बारे में TDS प्रोटोकॉल ठीक यही बात करता है घटना का उल्लेख है; देखें टिप्पणियां MSDN पर SET NOCOUNT कमांड का।)

व्यक्तिगत रूप से, मैंने SQLCMD.EXE के अपने "क्लोन" में सफलता के साथ इस दृष्टिकोण का उपयोग किया है।

अपडेट करें :यह ध्यान दिया जाना चाहिए, कि इस दृष्टिकोण (बेशक) के लिए आपको इनपुट स्क्रिप्ट/कथनों को GO पर मैन्युअल रूप से विभाजित करने की आवश्यकता है विभाजक, क्योंकि आप SqlCommand.Execute*() . का उपयोग करने के लिए वापस आ गए हैं जो एक बार में कई बैचों को हैंडल नहीं कर सकता है। इसके लिए कई विकल्प हैं:

  • मैन्युअल रूप से इनपुट को GO . से शुरू होने वाली पंक्तियों में विभाजित करें (चेतावनी:GO GO 5 . की तरह कहा जा सकता है , उदाहरण के लिए, पिछले बैच को 5 बार निष्पादित करने के लिए)।
  • ManagedBatchParser का उपयोग करें क्लास/लाइब्रेरी इनपुट को एकल बैचों में विभाजित करने में आपकी मदद करने के लिए, विशेष रूप से ICommandExecutor.ProcessBatch उपरोक्त कोड के साथ (या इससे मिलता-जुलता कुछ)।

मैं बाद का विकल्प चुनता हूं, जो काफी काम था, यह देखते हुए कि यह बहुत अच्छी तरह से प्रलेखित नहीं है और उदाहरण दुर्लभ हैं (थोड़ा सा Google, आपको कुछ सामान मिलेगा, या परावर्तक का उपयोग करके देखें कि एसएमओ-असेंबली उस वर्ग का उपयोग कैसे करते हैं) ।

ManagedBatchParser . का उपयोग करने का लाभ (और शायद बोझ) यह है कि यह टी-एसक्यूएल स्क्रिप्ट के अन्य सभी निर्माणों को भी पार्स करेगा (SQLCMD.EXE के लिए अभिप्रेत है) ) आपके लिए। शामिल हैं::setvar , :connect , :quit , आदि। आपको संबंधित ICommandExecutor . को लागू करने की आवश्यकता नहीं है सदस्य, यदि आपकी स्क्रिप्ट निश्चित रूप से उनका उपयोग नहीं करती हैं। लेकिन ध्यान रहे कि आप "मनमाने ढंग से" स्क्रिप्ट निष्पादित करने में सक्षम नहीं होंगे।

ठीक है, क्या आपने इसे रखा था। "... प्रभावित पंक्तियों" को प्रिंट करने के "सरल प्रश्न" से इस तथ्य तक कि यह एक मजबूत और सामान्य तरीके से करने के लिए तुच्छ नहीं है (आवश्यक पृष्ठभूमि कार्य को देखते हुए)। वाईएमएमवी, शुभकामनाएँ।

प्रबंधित बैचपार्सर उपयोग पर अपडेट करें

IBatchSource को कैसे लागू किया जाए, इस बारे में कोई अच्छा दस्तावेज या उदाहरण नहीं है , यहाँ मैं क्या लेकर गया था।

internal abstract class BatchSource : IBatchSource
{
    private string m_content;

    public void Populate()
    {
        m_content = GetContent();
    }

    public void Reset()
    {
        m_content = null;
    }

    protected abstract string GetContent();

    public ParserAction GetMoreData(ref string str)
    {
        str = null;

        if (m_content != null)
        {
            str = m_content;
            m_content = null;
        }

        return ParserAction.Continue;
    }
}

internal class FileBatchSource : BatchSource
{
    private readonly string m_fileName;

    public FileBatchSource(string fileName)
    {
        m_fileName = fileName;
    }

    protected override string GetContent()
    {
        return File.ReadAllText(m_fileName);
    }
}

internal class StatementBatchSource : BatchSource
{
    private readonly string m_statement;

    public StatementBatchSource(string statement)
    {
        m_statement = statement;
    }

    protected override string GetContent()
    {
        return m_statement;
    }
}

और आप इसका उपयोग इस प्रकार करेंगे:

var source = new StatementBatchSource("SELECT GETUTCDATE()");
source.Populate();

var parser = new Parser(); 
parser.SetBatchSource(source);
/* other parser.Set*() calls */

parser.Parse();

ध्यान दें कि दोनों कार्यान्वयन, या तो सीधे बयानों के लिए (StatementBatchSource ) या फ़ाइल के लिए (FileBatchSource ) उन्हें समस्या है कि वे एक ही बार में पूरा पाठ स्मृति में पढ़ लेते हैं। मेरे पास एक ऐसा मामला था, जिसमें एक विशाल (!) स्क्रिप्ट थी, जिसमें उत्पन्न INSERT के गैज़िलियन थे। बयान। हालांकि मुझे नहीं लगता कि यह एक व्यावहारिक मुद्दा है, SQLCMD.EXE इसे संभाल सकता था। लेकिन मेरे जीवन के लिए, मैं यह नहीं समझ सका कि वास्तव में, आपको IBatchParser.GetContent() के लिए लौटाए गए भाग बनाने की आवश्यकता होगी। ताकि पार्सर अभी भी उनके साथ काम कर सके (ऐसा लगता है कि उन्हें पूर्ण बयान देने की आवश्यकता होगी, जो पहले स्थान पर पार्स के उद्देश्य को हरा देगा...)।




  1. DBeaver
  2.   
  3. phpMyAdmin
  4.   
  5. Navicat
  6.   
  7. SSMS
  8.   
  9. MySQL Workbench
  10.   
  11. SQLyog
  1. क्या SQL क्वेरी से परिणाम को सीधे संपीड़ित/ज़िप करने का कोई तरीका है?

  2. प्रबंधन स्टूडियो में परिणामसेट कॉलम की चौड़ाई

  3. SQL सर्वर:एक अलग/क्षतिग्रस्त डेटाबेस को कैसे संलग्न/मरम्मत करें?

  4. असमान प्रतिशत बकेट में विभाजित सेट

  5. SSMS 2012 इंटेलिजेंस बिहेवियर