Желательно ли использовать временную таблицу, когда хранимая процедура может выполняться одновременно разными пользователями?

8

Я работаю над хранимой процедурой, которая получает objectGUID из активного каталога. Я сохраняю результат во временной таблице, а затем возвращаю значение в выходном параметре для использования с другими процессами. SP будет вызываться из разных хранимых процедур, а также из веб-приложений PHP, ASP Classic и ASP.Net.

Я читал ЗДЕСЬ, что (относительно временных таблиц):

Если они созданы внутри хранимой процедуры, они уничтожаются по завершении хранимой процедуры. Кроме того, областью действия любой конкретной временной таблицы является сеанс, в котором она создается; это означает, что он виден только текущему пользователю. Несколько пользователей могут создать временную таблицу с именем #TableX, и любые одновременные запросы не будут влиять друг на друга - они будут оставаться автономными транзакциями, а таблицы будут оставаться автономными объектами. Вы можете заметить, что мое имя временной таблицы начиналось со знака «#».

Похоже, я в порядке, но я хотел получить совет, чтобы убедиться, что нет никаких ошибок, о которых я не знаю. Вот ИП.

Заранее спасибо.

CREATE PROCEDURE stp_adlookup
@user varchar(100),
@objectGUID varbinary(256) OUTPUT
AS
SET NOCOUNT ON;
DECLARE @qry char(1000)
CREATE TABLE #tmp(
objectGUID nvarchar(256)
)

SET @qry = 'SELECT *
FROM openquery(ADSI, ''
SELECT  objectGUID              
FROM    ''''LDAP://mydomaincontroller.com''''
WHERE sAMAccountName = ''''' + @user + '''''
'')'
INSERT INTO #tmp
EXEC(@qry)
SELECT @objectGUID=CAST(objectGUID as varbinary(256))  FROM #tmp;
DROP TABLE #tmp
SET NOCOUNT OFF;
GO
user1633947
источник

Ответы:

15

Да, каждый пользователь получит свою собственную копию таблицы #temp, даже если он будет запущен в одно и то же время.

(Однако не используйте глобальные временные таблицы ##, обозначенные двумя ведущими символами фунта / хеша.)

Но зачем вам здесь таблица #temp? Нечто подобное должно работать (не проверено, поскольку у меня нет LDAP где-то рядом со мной):

CREATE PROCEDURE dbo.stp_adlookup -- ALWAYS use schema prefix
  @user varchar(100),
  @objectGUID varbinary(256) OUTPUT
AS
BEGIN -- use body wrappers
  SET NOCOUNT ON;

  DECLARE @qry nvarchar(max); -- don't use CHAR for dynamic SQL

  SET @qry = N'SELECT @o = objectGUID
    FROM openquery(ADSI, ''SELECT  objectGUID              
      FROM    ''''LDAP://mydomaincontroller.com''''
      WHERE sAMAccountName = ''''' + @user + ''''''')';

  -- can probably parameterize the above, but those single
  -- quotes are a nightmare. Not sure if they're necessary
  -- but I do not feel like trying to untangle them.

  EXEC sys.sp_executesql @qry, N'@o UNIQUEIDENTIFIER', @o = @objectGUID OUTPUT;

  -- SET NOCOUNT OFF; -- don't do this.
END
GO
Аарон Бертран
источник
8

Вы должны быть в порядке, у нас есть бесчисленные SP, которые запускаются 1000 раз в день с временными таблицами, которые имеют одинаковые имена и не имеют проблем.

Вот наглядный пример. Я создал 2 таблицы на своем экземпляре SQL2014. Один был создан из SPID 53, другой из SPID 57. Вот как это выглядит в Object Explorer:

введите описание изображения здесь

Как вы можете видеть, хотя они и названы одинаково, в самом конце есть прекрасный набор символов, которые отличают таблицы. Разница лишь в том, что я выполнил операторы CREATE из разных окон запросов. Это просто визуальный способ показать это. Когда вы запрашиваете таблицу #tmp, вы запрашиваете только таблицу, которая относится к вашему сеансу.

Я сделаю одно предложение, хотя. Это то, что я полностью виноват, и я работаю над переходом к. Используйте sp_executesqlвместо EXEC(). Аарон Бертран написал это как одно из «плохих привычек к удару»:

По сути, использование sp_executesql уменьшит вероятность внедрения SQL-кода, и есть большая вероятность повторного использования плана выполнения. Аарон подробно разбирается в статье, но это 1000-футовый обзор.

Крис Груттемейер
источник
5
Я хотел бы просто добавить, что может быть полезно присваивать имена локальным временным таблицам уникально для каждой процедуры, потому что процедура может быть вызвана из другой процедуры, которая уже создала локальную временную таблицу с тем же именем.
Пол Уайт 9
2

в широком смысле, вам будет хорошо, если вы будете так делать. Хранимые процедуры имеют ограниченную область действия, поэтому, хотя (пример) 3 пользователя выполняют одну и ту же хранимую процедуру, и временные таблицы не будут смешиваться, они даже не будут видеть друг друга.

До тех пор, пока вам не нужно делиться результатами с другим сеансом или пользователем, выполняющим другой процесс, временная таблица может быть совершенно разумным способом.

Брэд Д
источник