AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 120131
Accepted
JohnG
JohnG
Asked: 2015-11-05 14:11:43 +0800 CST2015-11-05 14:11:43 +0800 CST 2015-11-05 14:11:43 +0800 CST

gatilhos - usando as tabelas inseridas/excluídas no SQL dinâmico

  • 772

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?

sql-server trigger
  • 2 2 respostas
  • 6185 Views

2 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2015-11-05T22:12:59+08:002015-11-05T22:12:59+08:00

    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:

    • Dependendo de quantas tabelas este Trigger será colocado e/ou com que frequência as operações DML são, isso pode causar pequenos problemas de desempenho no(s) banco(s) de dados onde este Trigger está criando as tabelas porque a criação de tabelas requer um Schema-Lock (I acredito) e fazer isso com muita frequência pode complicar algumas outras operações.
    • Se este Trigger for colocado em mais de uma Tabela, como você distinguirá as operações entre as diferentes Tabelas (a menos que dê a elas seu próprio prefixo para as tabelas criadas dinamicamente)?
    • Você tem um UpdatedDateou 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.
    • Como você planeja limpar todas essas várias tabelas? Talvez seja melhor criar um Schema só para segurar essas tabelas?
    • Você planeja indicar em algum lugar a operação DML que ocorreu?
    • Se você quiser rastrear os valores "antes" e "depois" em um UPDATE, precisará capturar as tabelas insertede . deletedMas 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 as insertedtabelas deletedna tabela já existente e apenas usar um GUID ou INT de uma sequência para correlacionar entre 2 linhas da mesma UPDATEoperação .
    • Dependendo de qual versão e edição do SQL Server você está usando, você pode querer olhar para Change Tracking e Change Data Capture .

    No entanto, com tudo isso dito, a questão da interação com as tabelas insertede por meio do SQL dinâmico é um problema interessante. deletedInfelizmente, 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 insertede deleted, portanto, parece que os gatilhos SQLCLR podem acessar as tabelas insertede deletedno 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 com PERMISSION_SET = SAFE; não há necessidade de uma Chave Assimétrica ou de definir o banco de dados para TRUSTWORTHY 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):

    CREATE TABLE TableThatHasTriggers
    (
       TableThatHasTriggersID INT IDENTITY(1, 1) NOT NULL
                              CONSTRAINT [PK_TableThatHasTriggers] PRIMARY KEY, 
       InsertTime DATETIME NOT NULL
                  CONSTRAINT [DF_TableThatHasTriggers_InsertTime] DEFAULT (GETDATE()),
       SomeValue NVARCHAR(50) COLLATE Latin1_General_100_CI_AS NULL
    );
    

    O código SQLCLR C#:

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using Microsoft.SqlServer.Server;
    
    public class Triggers
    {
        [SqlTrigger(Target = "TableThatHasTriggers", Event = "FOR INSERT, UPDATE")]
        public static void tr_TableThatHasTriggers_audit()
        {
            string _AuditSQL = @"
                    SELECT ins.*
                    INTO   dbo.[TMPIns_" + Guid.NewGuid().ToString().Replace("-", "") + @"]
                    FROM   INSERTED ins;
    ";
    
            SqlConnection _Connection = new SqlConnection("Context Connection = true");
            SqlCommand _Command = _Connection.CreateCommand();
            _Command.CommandText = _AuditSQL;
    
            // SqlContext.Pipe.Send(_AuditSQL); // display query for debugging purposes ONLY
    
            try
            {
                _Connection.Open();
                _Command.ExecuteNonQuery();
            }
            finally
            {
                _Command.Dispose();
                _Connection.Dispose();
            }
        }
    }
    

    Objeto wrapper T-SQL para colocar o gatilho SQLCLR na tabela:

    CREATE TRIGGER [dbo].[tr_TableThatHasTriggers_SQLCLRaudit]
      ON [dbo].[TableThatHasTriggers]
      AFTER INSERT, UPDATE
      AS EXTERNAL NAME
                 [InsertedTableViaDynamicSQL].[Triggers].[tr_TableThatHasTriggers_SQLCLRaudit];
    
    • 2
  2. Eske Rahn
    2020-07-01T13:46:55+08:002020-07-01T13:46:55+08:00

    (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.

    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve