/ / Escopo de tabelas temporárias no SQL Server - sql, sql-server, tsql, sql-server-2012

Escopo de tabelas temporárias no SQL Server - sql, sql-server, tsql, sql-server-2012

Eu escrevi um procedimento armazenado para importar e transformar dados de um banco de dados para outro. Cada importação usaria um único ID da empresa e importaria todos os dados relacionados a essa empresa.

Para ajudar na etapa de transformação, eu usotabelas temporárias. Como parte da revisão do script, me disseram para usar variáveis ​​de tabela em vez de tabelas temporárias. O revisor afirma que, se executarmos duas importações diferentes ao mesmo tempo, a tabela temporária será compartilhada e danificará a importação.


Questões:

  • É verdade que a tabela temporária seria compartilhada se executarmos duas importações diferentes ao mesmo tempo?
  • Cada chamada para EXEC criar um novo escopo?

Aqui está um exemplo artificial do script.

CREATE PROC [dbo].[ImportCompany]
(
@CompanyId AS INTEGER
)
AS
EXEC [dbo].[ImportAddress] @CompanyId = @CompanyId
--Import other data

CREATE PROC [dbo].[ImportAddress]
(
@CompanyId AS INTEGER
)
AS
CREATE TABLE #Companies (OldAddress NVARCHAR(128), NewAddress NVARCHAR(128))
INSERT INTO #Companies(OldAddress, NewAddress)
SELECT
Address as OldAddress,
"Transformed " + Address as NewAddress
FROM
[OldDb].[dbo].[Addresses]
WHERE
CompanyId = @CompanyId

--Do stuff with the transformed data

DROP TABLE #Companies

EXEC [dbo].[ImportCompany] @CompanyId = 12345

Respostas:

45 para resposta № 1

A partir de CREATE TABLE:

As tabelas temporárias locais são visíveis apenas na sessão atual

e (mais importante):

Se uma tabela temporária local for criada em umprocedimento ou aplicativo que pode ser executado ao mesmo tempo por vários usuários, o Mecanismo de Banco de Dados deve poder distinguir as tabelas criadas pelos diferentes usuários. O Mecanismo de Banco de Dados faz isso anexando internamente um sufixo numérico a cada nome de tabela temporária local.

O que exatamente refuta o argumento de quem disse que seria compartilhado.


Além disso, não há necessidade de DROP TABLE no final do seu procedimento (do mesmo link novamente):

Uma tabela temporária local criada em um procedimento armazenado é descartada automaticamente quando o procedimento armazenado é concluído


22 para resposta № 2

## é usado para tabelas temporárias globais - estará disponível para as diferentes importações.

# é usado para tabelas temporárias locais e disponível apenas no escopo atual / interno.


17 for answer № 3

Uma sessão não pode ver as tabelas temporárias de outra sessão. Portanto, importações diferentes não afetarão uma a outra, independentemente de você usar tabelas temporárias ou variáveis ​​de tabela.

A exceção são as tabelas temporárias globais, que começam com ##. Esses são visíveis para todas as conexões.


-1 para resposta № 4

Passei algumas horas lutando para descobrirpor que uma tabela temporária usada em um gatilho se comportou de maneira estranha. Então percebi que a tabela temporária tinha o mesmo nome de uma tabela temporária no procedimento armazenado usado para inserir os dados que acionaram o gatilho. Agora estou ciente de que isso deveria ter sido óbvio para mim imediatamente, mas era um caso típico de negligenciar a causa mais óbvia ao tentar descobrir por que algo não fazia sentido.

Portanto, é importante lembrar que, quando um processo armazenado chama outro processo armazenado ou dispara um gatilho, os nomes das tabelas temporárias precisam ser exclusivos entre eles para evitar efeitos colaterais indesejados.

Além disso - mesmo ao executar o seguinte código no processo armazenado interno, ele não funcionará conforme o esperado. Como o processo armazenado externo parece bloquear o nome da tabela temporária.

IF OBJECT_ID("tempdb..#TempTable") IS NOT NULL
DROP TABLE #TempTable