เป็นไปได้ไหมที่คำสั่ง SQL จะรันพร้อมกันภายในเซสชันเดียวใน SQL Server?


16

ฉันได้เขียนขั้นตอนการจัดเก็บซึ่งใช้ประโยชน์จากตารางชั่วคราว ฉันรู้ว่าใน SQL Server ตารางชั่วคราวมีการกำหนดขอบเขตเซสชัน อย่างไรก็ตามฉันไม่สามารถค้นหาข้อมูลที่ชัดเจนเกี่ยวกับสิ่งที่เซสชันสามารถทำได้ โดยเฉพาะอย่างยิ่งถ้าเป็นไปได้สำหรับขั้นตอนการจัดเก็บนี้เพื่อดำเนินการสองครั้งพร้อมกันในเซสชั่นเดียวระดับการแยกที่สูงขึ้นอย่างมีนัยสำคัญเป็นสิ่งจำเป็นสำหรับการทำธุรกรรมภายในกระบวนการดังกล่าวเนื่องจากการประหารชีวิตทั้งสอง

คำตอบ:


19

ในขณะที่คำตอบของ Brent นั้นถูกต้องสำหรับการใช้งานจริงทั้งหมดและนี่ไม่ใช่สิ่งที่ฉันเคยเห็นใครบางคนกังวล แต่เป็นไปได้ที่การเรียกใช้กระบวนงานที่เก็บไว้ในเซสชันหลายครั้งเพื่อส่งผลกระทบต่อกันผ่านตาราง #temp .

ข่าวดีก็คือมันเป็นอย่างมากน่าจะเกิดขึ้นในป่าเพราะ

1) #Temp ตารางที่ประกาศไว้ในขั้นตอนการจัดเก็บหรือแบทช์ซ้อนกันไม่ได้มีการเปิดเผยเซสชัน (หรืออายุการใช้งาน) และเหล่านี้คือไกลโดยกรณีที่พบมากที่สุด

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

และด้วยตาราง temp ที่ประกาศไว้ภายในโพรซีเดอร์หากคุณเปลี่ยนเคียวรีที่สองเป็น

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

มันล้มเหลวด้วย:

'ชื่อวัตถุไม่ถูกต้อง' #t '.'

เนื่องจากตาราง #temp ที่สร้างขึ้นภายในกระบวนงานที่เก็บไว้หรือแบทช์ซ้อนจะมองเห็นได้เฉพาะในขั้นตอนหรือชุดงานที่จัดเก็บนั้นและในขั้นตอนที่ซ้อนและชุดงานที่เรียกใช้และถูกทำลายเมื่อขั้นตอนหรือชุดสิ้นสุด


12

ไม่พร้อมกัน ตัวเลือกของคุณรวมถึง:

  • เรียกใช้แบบสอบถามหนึ่งหลังจากนั้นอีกในเซสชันเดียวกัน
  • สลับจากตารางชั่วคราวเป็นตารางชั่วคราวทั่วโลก (ใช้ ## TableName แทน #TableName) แต่โปรดทราบว่าตารางชั่วคราวทั่วโลกจะถูกลบโดยอัตโนมัติเมื่อเซสชันที่สร้างตารางชั่วคราวปิดและไม่มีเซสชันอื่นที่ใช้งานอยู่ด้วย อ้างอิงถึงมัน
  • เปลี่ยนเป็นตารางผู้ใช้จริงใน TempDB - คุณสามารถสร้างตารางที่นั่น แต่ระวังว่าจะหายไปเมื่อรีสตาร์ทเซิร์ฟเวอร์
  • สลับเป็นตารางผู้ใช้จริงในฐานข้อมูลผู้ใช้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.