E aí ##pessoal,
Dando continuidade à série de posts sobre Tabelas Temporárias, nesse segundo post vou falar sobre Tabelas Temporárias Globais. #gogogo
Dicas T-SQL – Tabelas Temporárias – Parte 1 – Tabelas Locais
Dicas T-SQL – Tabelas Temporárias – Parte 2 – Tabelas Globais
Dicas T-SQL – Tabelas Temporárias – Parte 3 – Tabelas Variáveis
Se você não viu o primeiro post da série, recomendo fortemente que veja antes de continuar a leitura desse post OK. #ficaadica
Tabelas Temporárias Globais:
No post anterior, eu expliquei que as Tabelas Temporárias Locais ficam visíveis apenas para a sessão que cria a tabela.
Já as Tabelas Temporárias Globais ficam visíveis para qualquer sessão, ou seja, qualquer sessão pode acessar ou alterar essa tabela!
Isso pode ser útil quando precisamos compartilhar algumas informações para mais de uma sessão de forma temporária.
“Luiz, como eu faço pra criar uma Tabela Temporária Global? É muito diferente das Tabelas Temporárias Locais?”
É bem parecido! Para criar uma Tabela Temporária Global o nome da tabela deve começar sempre com o prefixo “##” (nas Tabelas Temporárias Locais o prefixo é o “#”). Segue um exemplo de criação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
USE Traces -- TABELA TEMPORARIA LOCAL CREATE TABLE #TESTE_TEMPORARIA_LOCAL ( Id INT IDENTITY(1,1), Nome VARCHAR(100) ) INSERT INTO #TESTE_TEMPORARIA_LOCAL VALUES('TESTE 1 - TABELA TEMPORARIA LOCAL') -- TABELA TEMPORARIA GLOBAL CREATE TABLE ##TESTE_TEMPORARIA_GLOBAL ( Id INT IDENTITY(1,1), Nome VARCHAR(100) ) INSERT INTO ##TESTE_TEMPORARIA_GLOBAL VALUES('TESTE 2 - TABELA TEMPORARIA GLOBAL') -- RETORNANDO OS DADOS DAS TABELAS SELECT * FROM #TESTE_TEMPORARIA_LOCAL SELECT * FROM ##TESTE_TEMPORARIA_GLOBAL |
Agora vamos abrir uma nova sessão e tentar fazer um SELECT na Tabela Temporária Local. Será gerado um erro, pois essa tabela só é visível na sessão que criou a tabela.
1 |
SELECT * FROM #TESTE_TEMPORARIA_LOCAL |
Msg 208, Level 16, State 0, Line 1
Invalid object name ‘#TESTE_TEMPORARIA_LOCAL’.
Ainda nessa nova sessão, vamos inserir um novo registro na Tabela Temporária Global e fazer um SELECT.
1 2 3 4 |
INSERT INTO ##TESTE_TEMPORARIA_GLOBAL VALUES('TESTE 3 - TABELA TEMPORARIA GLOBAL') SELECT * FROM ##TESTE_TEMPORARIA_GLOBAL |
Repare que dessa vez o comando foi executado com sucesso e o registro foi inserido através de uma outra sessão! Show!!!
Contudo, também temos que tomar um pouco de cuidado, pois podemos ter alguns efeitos colaterais com alterações nessas tabelas globais. Como podemos ver, uma outra sessão também pode fazer alterações nessas tabelas e isso pode alterar o resultado que era esperado antes da alteração.
Vamos ver essa situação com outro exemplo:
Primeiro, vamos fazer um SELECT e um COUNT para retornar a quantidade de registros da Tabela Temporária Global. Nesse momento irá retornar o valor 2.
1 2 |
SELECT COUNT(*) AS Qt_Registros FROM ##TESTE_TEMPORARIA_GLOBAL |
Agora abra uma nova sessão e execute o DELETE para excluir os registros da tabela.
1 |
DELETE ##TESTE_TEMPORARIA_GLOBAL |
(2 rows affected)
Por fim, faça novamente o SELECT e o COUNT na primeira sessão que estava aberta. Dessa vez, o resultado será 0!
1 2 |
SELECT COUNT(*) AS Qt_Registros FROM ##TESTE_TEMPORARIA_GLOBAL |
Agora imagine se isso acontecer em alguma das situações abaixo:
- Se isso acontecer em uma rotina crítica do seu ambiente?
- Será que o cliente ficará feliz com um resultado incorreto?
- Qual será o impacto desse resultado incorreto?
- Esse “efeito colateral” foi avaliado na implantação?
Podemos fazer vários questionamentos sobre essa questão. A ideia nesse post é mostrar como as Tabelas Temporárias Globais podem ser muito úteis e ao mesmo tempo muito perigosas!
Portanto, USE COM MODERAÇÃO!!!
Quando uma Tabela Temporária Global é excluída?
Uma Tabela Temporária Global será excluída quando a sessão que a criou for finalizada (e todas as referências ativas para ela também) ou se a tabela for dropada explicitamente.
Vamos ver mais dois casos de exemplo.
Exemplo 1:
Abra uma nova sessão e execute o script abaixo para criar uma nova Tabela Temporária Global.
1 2 3 4 5 6 7 8 9 |
CREATE TABLE ##TESTE_EXCLUSAO_GLOBAL ( Id INT IDENTITY(1,1), Nome VARCHAR(100) ) INSERT INTO ##TESTE_EXCLUSAO_GLOBAL VALUES('TESTE - TABELA EXCLUSÃO GLOBAL') SELECT * FROM ##TESTE_EXCLUSAO_GLOBAL |
Depois abra uma outra sessão e execute somente o SELECT. O script será executado com sucesso e o resultado será o mesmo do print anterior.
Agora feche apenas a primeira sessão e tente executar novamente o SELECT com a sessão que ficou aberta. Dessa vez será gerado um erro, pois a sessão que tinha criado a tabela foi encerrada e ela não tinha nenhuma referência ativa.
Msg 208, Level 16, State 0, Line 1
Invalid object name ‘##TESTE_EXCLUSAO_GLOBAL’.
Exemplo 2:
Vamos repetir o procedimento do exemplo anterior para criar a Tabela Temporária Global.
1 2 3 4 5 6 7 8 9 |
CREATE TABLE ##TESTE_EXCLUSAO_GLOBAL ( Id INT IDENTITY(1,1), Nome VARCHAR(100) ) INSERT INTO ##TESTE_EXCLUSAO_GLOBAL VALUES('TESTE - TABELA EXCLUSÃO GLOBAL') SELECT * FROM ##TESTE_EXCLUSAO_GLOBAL |
Agora abra uma outra sessão e execute o script abaixo que vai abrir uma transação com o BEGIN TRAN e inserir um novo registro na tabela. Ainda não vamos finalizar essa transação OK.
1 2 3 4 5 6 |
BEGIN TRAN INSERT INTO ##TESTE_EXCLUSAO_GLOBAL VALUES('INSERT COM BEGIN TRAN - TABELA EXCLUSÃO GLOBAL') SELECT * FROM ##TESTE_EXCLUSAO_GLOBAL |
Se você tentar fazer um SELECT na tabela utilizando a primeira sessão, você será bloqueado, pois a outra sessão iniciou uma transação e será gerado um LOCK.
1 |
EXEC sp_whoisactive |
Agora vamos encerrar a primeira sessão e fazer novamente o SELECT através da sessão que deixou a transação aberta.
1 |
SELECT * FROM ##TESTE_EXCLUSAO_GLOBAL |
Repare que nesse momento a sessão que criou a Tabela Temporária Global já foi encerrada, mas a tabela ainda não foi dropada porque ainda existe uma referência ativa (devido ao BEGIN TRAN e o INSERT que fizemos antes).
Agora vamos finalizar a transação executando um COMMIT.
1 |
COMMIT |
Por fim, vamos tentar fazer novamente o SELECT na tabela. Contudo, dessa vez será gerado um erro, pois no momento que nós fizemos o COMMIT a referência ativa foi encerrada e a tabela foi dropada.
1 |
SELECT * FROM ##TESTE_EXCLUSAO_GLOBAL |
Msg 208, Level 16, State 0, Line 13
Invalid object name ‘##TESTE_EXCLUSAO_GLOBAL’.
Achei interessante esse exemplo e resolvi compartilhar com vocês também. =)
Referências:
Segue abaixo mais alguns links como referência:
https://www.red-gate.com/simple-talk/sql/t-sql-programming/temporary-tables-in-sql-server/
Espero que tenha gostado e que isso também possa ser útil no seu dia a dia. Até o próximo post!
Me siga no LinkedIn e no Facebook para ficar por dentro das novidades.
Abraço,
Luiz Vitor França Lima
Consultor SQL Server
Muito bom Luiz!!!
Valeu Anderson!!! Que bom que gostou =)
Abraço,
Luiz Vitor
Pingback: Dicas T-SQL – Tabelas Temporárias – Parte 1 – Tabelas Locais – Luiz Lima
Pingback: Dicas T-SQL – Tabelas Temporárias – Parte 3 – Tabelas Variáveis – Luiz Lima