É aconselhável usar uma tabela temporária quando o procedimento armazenado puder ser executado simultaneamente por diferentes usuários?

8

Estou trabalhando em um procedimento armazenado que recupera o objectGUID do diretório ativo. Estou armazenando o resultado em uma tabela temporária e retornando o valor em um parâmetro de saída para uso com outros processos. O SP será chamado a partir de diferentes procedimentos armazenados, bem como dos aplicativos Web PHP, ASP Classic e ASP.Net.

Li AQUI que (em relação às tabelas temporárias):

Se criados dentro de um procedimento armazenado, eles são destruídos após a conclusão do procedimento armazenado. Além disso, o escopo de qualquer tabela temporária específica é a sessão em que é criada; ou seja, é visível apenas para o usuário atual. Vários usuários podem criar uma tabela temporária chamada #TableX e quaisquer consultas executadas simultaneamente não afetariam um ao outro - elas permaneceriam transações autônomas e as tabelas permaneceriam objetos autônomos. Você pode perceber que meu nome de tabela temporária de exemplo começou com um sinal "#".

Parece que estou pronto para ir, mas queria obter alguns conselhos para garantir que não houvesse nenhum problema. Aqui está o SP.

Desde já, obrigado.

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
fonte

Respostas:

15

Sim, cada usuário receberá sua própria cópia da tabela #temp, mesmo que seja executado exatamente ao mesmo tempo.

(No entanto, não use tabelas ## temp globais, representadas com dois sinais de libra / hash principais.)

Mas por que você precisa de uma tabela #temp aqui? Algo assim deve funcionar (não testado, pois não tenho LDAP perto de mim):

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
Aaron Bertrand
fonte
8

Você deve ficar bem, temos inúmeros SPs aqui que são executados milhares de vezes por dia com tabelas temporárias com o mesmo nome e sem problemas.

Aqui está um exemplo visual. Eu criei 2 tabelas na minha instância do SQL2014. Um foi criado a partir do SPID 53, o outro a partir do SPID 57. Veja como é o Object Explorer:

insira a descrição da imagem aqui

Como você pode ver, apesar de terem o mesmo nome, no final, há um conjunto adorável de caracteres que tornam as tabelas diferentes. A única diferença é que eu executei as instruções CREATE de diferentes janelas de consulta. Esta é apenas uma maneira visual de mostrá-lo. Ao consultar a tabela #tmp, você consulta apenas a tabela que se aplica à sua sessão.

Farei uma sugestão, no entanto. É algo de que sou completamente culpado e estou trabalhando na transição para. Use em sp_executesqlvez de EXEC(). Aaron Bertrand escreveu isso como um dos 'maus hábitos para chutar':

Basicamente, o uso de sp_executesql reduzirá a chance de injeção de SQL e há uma chance maior de que o plano de execução possa ser reutilizado. Aaron entra em muito mais detalhes no artigo, mas essa é a visão de 1000 pés.

Kris Gruttemeyer
fonte
5
Gostaria de acrescentar que pode ser útil nomear tabelas temporárias locais exclusivamente por procedimento, porque o procedimento pode ser chamado de outro procedimento que já criou uma tabela temporária local com o mesmo nome.
Paul White 9
2

do ponto de vista amplo, você ficará bem em fazê-lo dessa maneira. Os procedimentos armazenados têm escopo limitado, portanto, mesmo que (por exemplo) três usuários executem o mesmo procedimento armazenado e as tabelas temporárias não sejam combinadas, elas nem se verão.

Contanto que você não precise compartilhar os resultados com uma sessão diferente ou com um usuário executando um processo diferente, a tabela Temp pode ser um caminho perfeitamente correto.

Brad D
fonte