Dentro de uma trigger, estou tentando criar um nome de tabela único (usando o NEWID()
) onde possa armazenar os dados que se encontram nas tabelas inseridas e deletadas.
Declare @NewID varchar(50) = Replace(convert(Varchar(50),NEWID()),'-','')
Declare @SQLStr varchar(8000)
Set @SQLStr= 'Select * into [TMPIns' + @newID + '] from inserted'
Exec (@SQLStr)
Recebo o seguinte erro: Nome de objeto inválido 'inserted'
Eu sei que posso fazer:
Select * into #inserted from inserted
Set @SQLStr= 'Select * into [TMPIns' + @newID + '] from #inserted'
Exec (@SQLStr)
Mas não quero usar o TempDB, pois essas tabelas podem ficar grandes e também acho redundante. Existe uma maneira de evitar a criação de #inserted?
Sem mais informações sobre o objetivo pretendido dessa solicitação, certamente parece que, mesmo com esse problema imediato resolvido, o código de trabalho pode não fornecer nada realmente útil. Algumas preocupações são:
UpdatedDate
ou algum campo de data na tabela? Caso contrário, não há senso de cronologia sem olhar para a data de criação da tabela.UPDATE
, precisará capturar as tabelasinserted
e .deleted
Mas se eles tiverem nomes baseados em GUID, você não poderá correlacionar entre as tabelas de cópia "inseridas" e "excluídas" para uma determinada operação UPDATE. Você teria que reutilizar o mesmo valor GUID e denotar "inserir" ou "excluir" no prefixo do nome da tabela. Se você não estivesse criando a tabela dinamicamente, poderia incluir uma coluna especificando a ação DML, despejar ambas asinserted
tabelasdeleted
na tabela já existente e apenas usar um GUID ou INT de uma sequência para correlacionar entre 2 linhas da mesmaUPDATE
operação .No entanto, com tudo isso dito, a questão da interação com as tabelas
inserted
e por meio do SQL dinâmico é um problema interessante.deleted
Infelizmente, isso não pode ser feito em T-SQL. Então agora também é um desafio :-). Felizmente, isso pode realmente ser feito. Como assim? Com uma ajudinha do nosso amigo Mr SQLCLR.Agora, não parece haver muitas situações que realmente exijam ou mesmo se beneficiem de Triggers SQLCLR. Eles parecem ser as coisas menos úteis que você pode criar com o SQLCLR. No entanto, aqui temos um cenário para o qual eles se encaixam perfeitamente. O SQL enviado do código SQLCLR é SQL dinâmico. E os gatilhos SQLCLR têm acesso às tabelas
inserted
edeleted
, portanto, parece que os gatilhos SQLCLR podem acessar as tabelasinserted
edeleted
no SQL dinâmico. Abaixo está o código que faz exatamente isso para realizar esta solicitação (observe que a conexão do banco de dados está usando a "Conexão de Contexto" em processo, portanto, o Assembly pode ser marcado comPERMISSION_SET = SAFE
; não há necessidade de uma Chave Assimétrica ou de definir o banco de dados paraTRUSTWORTHY ON
):Tabela de teste para o Trigger a ser criado (se estiver usando Visual Studio / SSDT, a definição da tabela deve ser incluída no projeto):
O código SQLCLR C#:
Objeto wrapper T-SQL para colocar o gatilho SQLCLR na tabela:
(Alguns anos depois....)
Na verdade, o que o título do tópico descreve PODE ser feito com T-SQL sob a condição de que você possa fazer o processamento do inserido com um cursor.
Ou seja: É permitido criar um cursor acessando [Inserted] e depois passar esse nome para o código dinâmico. Você pode até fazer com que o sql dinâmico faça todo o open, while, fetch, close e desaloque coisas.
Portanto, no exemplo do OP, isso não seria bom, mas no caso de um gatilho mais complexo percorrendo o inserido um por um para fazer coisas, essa poderia ser uma solução muito real.