क्या SQL कथनों के लिए SQL सर्वर में एकल सत्र के भीतर समवर्ती रूप से निष्पादित करना संभव है?


16

मैंने एक संग्रहीत प्रक्रिया लिखी है जो एक अस्थायी तालिका का उपयोग करती है। मुझे पता है कि SQL सर्वर में, अस्थायी टेबल सत्र-स्कॉप हैं। हालाँकि, मैं इस बारे में निश्चित जानकारी नहीं पा सका हूँ कि एक सत्र क्या सक्षम है। विशेष रूप से, यदि इस संग्रहित प्रक्रिया के लिए एकल सत्र में दो बार समवर्ती रूप से निष्पादित करना संभव है, तो उस प्रक्रिया के भीतर लेनदेन के लिए एक उच्चतर उच्च अलगाव स्तर की आवश्यकता होती है, क्योंकि दो निष्पादन अब एक अस्थायी तालिका साझा कर रहे हैं।

जवाबों:


19

जबकि ब्रेंट का जवाब सभी व्यावहारिक प्रयोजनों के लिए सही है, और यह कुछ मैं कभी के बारे में किसी चिंता देखा है नहीं है, यह है एक सत्र-दायरे वाले #temp तालिका के माध्यम से एक दूसरे को प्रभावित करने के लिए एक सत्र में एक संग्रहीत प्रक्रिया के कई आमंत्रण के लिए संभव ।

अच्छी खबर यह है कि यह है बेहद जंगली क्योंकि में होने की संभावना नहीं

1) एक संग्रहीत प्रक्रियाओं या नेस्टेड बैचों के अंदर घोषित # टैम्प टेबल वास्तव में सत्र दृश्यता (या जीवनकाल) नहीं है। और ये अब तक का सबसे आम मामला है।

2) इसके लिए MultipleActiveResultsets की आवश्यकता है और या तो कुछ बहुत ही अजीब async क्लाइंट प्रोग्रामिंग की आवश्यकता है, या संग्रहीत कार्यविधि के लिए बीच में एक परिणामी को वापस करने के लिए, और क्लाइंट पहले से परिणाम संसाधित करते समय संग्रहीत प्रक्रिया के किसी अन्य उदाहरण को कॉल करने के लिए।

यहाँ एक उदाहरण दिया गया है:

using System;
using System.Data.SqlClient;

namespace ado.nettest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var con = new SqlConnection("Server=localhost;database=tempdb;integrated security=true;MultipleActiveResultSets = True"))
            {
                con.Open();

                var procDdl = @"
create table #t(id int)
exec ('
create procedure #foo
as
begin
  insert into #t(id) values (1);
  select top 10000 * from sys.messages m, sys.messages m2;
  select count(*) rc from #t;
  delete from #t;
end
');
";
                var cmdDDL = con.CreateCommand();
                cmdDDL.CommandText = procDdl;
                cmdDDL.ExecuteNonQuery();

                var cmd = con.CreateCommand();
                cmd.CommandText = "exec #foo";
                using (var rdr = cmd.ExecuteReader())
                {
                    rdr.Read();

                    var cmd2 = con.CreateCommand();
                    cmd2.CommandText = "exec #foo";
                    using (var rdr2 = cmd2.ExecuteReader())
                    {

                    }

                    while (rdr.Read())
                    {

                    }
                    rdr.NextResult();
                    rdr.Read();
                    var rc = rdr.GetInt32(0);
                    Console.WriteLine($"Numer of rows in temp table {rc}");

                }


            }

            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}

जो आउटपुट देता है

Numer of rows in temp table 0
Hit any key to exit

क्योंकि संग्रहित प्रक्रिया का दूसरा आह्वान एक पंक्ति सम्मिलित करता है, और फिर #t से सभी पंक्तियों को हटा दिया है, जबकि पहले आह्वान ग्राहक को अपने पहले परिणाम से पंक्तियों को लाने के लिए इंतजार कर रहा था। ध्यान दें कि यदि पहला परिणाम छोटा था, तो पंक्तियों को बफर किया जा सकता है और क्लाइंट को कुछ भी भेजे बिना निष्पादन जारी रह सकता है।

अगर आप हिलते हैं

create table #t(id int)

संग्रहीत प्रक्रिया में यह आउटपुट:

Numer of rows in temp table 1
Hit any key to exit

और प्रक्रिया के अंदर घोषित अस्थायी तालिका के साथ , यदि आप दूसरी क्वेरी को बदलते हैं

cmd2.CommandText = "select * from #t";

यह विफल रहता है:

'अमान्य वस्तु का नाम' #t '।'

क्योंकि एक संग्रहीत प्रक्रिया या नेस्टेड बैच के अंदर बनाई गई एक # टैम्पिंग टेबल केवल उस संग्रहीत प्रक्रिया या बैच और नेस्टेड प्रक्रियाओं और बैचों में दिखाई देती है जिसे वह कॉल करता है, और प्रक्रिया या बैच समाप्त होने पर नष्ट हो जाता है।


12

समवर्ती नहीं। आपके विकल्पों में शामिल हैं:

  • उसी सत्र में एक के बाद एक प्रश्नों को चलाएं
  • एक अस्थायी तालिका से एक वैश्विक अस्थायी तालिका पर स्विच करें (#TableName के बजाय ## TableName का उपयोग करें), लेकिन ध्यान रखें कि वैश्विक अस्थायी तालिका स्वचालित रूप से हटा दी जाती है जब सत्र जो अस्थायी तालिका बंद कर देता है, और कोई सक्रिय सत्र नहीं होता है इसका एक संदर्भ
  • TempDB में एक वास्तविक उपयोगकर्ता तालिका पर स्विच करें - आप वहां तालिकाओं का निर्माण कर सकते हैं, लेकिन ध्यान रखें कि वे सर्वर पुनरारंभ पर गायब हो जाएंगे
  • उपयोगकर्ता डेटाबेस में एक वास्तविक उपयोगकर्ता तालिका पर स्विच करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.