Чи можливо оператори SQL одночасно виконуватись протягом одного сеансу в SQL Server?


16

Я написав збережену процедуру, яка використовує тимчасову таблицю. Я знаю, що в SQL Server тимчасові таблиці проходять сеанс. Однак я не зміг знайти остаточну інформацію про те, на що здатний сеанс. Зокрема, якщо є можливість, щоб ця збережена процедура виконувалась двічі одночасно за один сеанс, для транзакції в рамках цієї процедури необхідний значно вищий рівень ізоляції завдяки двом виконанням, які тепер мають спільну тимчасову таблицю.

Відповіді:


19

Хоча відповідь Брента правильна для всіх практичних цілей, і це не те, що я коли-небудь бачив, як хтось хвилюється, це це можливо для декількох викликів процедури, що в сесії впливають один на одного через контекст сеансу #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 - ви можете створювати таблиці там, але майте на увазі, що вони зникнуть при перезапуску сервера
  • Переключіться на реальну таблицю користувачів у базі даних користувачів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.