none
Trigger para simular uma FK RRS feed

  • Pergunta

  • Caros,

    É possível criar uma trigger para simular uma FK? Ou seja, antes de um registro ser inserido, deve ser verificado se um determinado valor existe em uma outra tabela, caso exista os dados são inseridos na tabela, caso contrário não saõ inseridos.

    segunda-feira, 22 de dezembro de 2014 11:00

Respostas

  • Douglas, 

         Pelo cenário que você citou, porque você não utiliza uma Constraint de Check?? Ela faz exatamente o que você está querendo!

         Por default a constraint de check não verifica dados em outras tabelas, mas é possível validar criando uma function. Criei um exemplo que cria uma constraint de check que verifica se o estado existe antes de inserir os dados na tabela de clientes. Veja se pode ajudá-lo:

    USE [master]
    GO
    CREATE DATABASE [Exemplo] 
    go
    
    USE [Exemplo]
    GO
    -- Cria a Tabela de Relacionamento a ser Verificada
    CREATE TABLE [dbo].[Estados](
    	[id] [int] IDENTITY(1,1) NOT NULL Primary Key,
    	[Estado] [char](2) NULL)
    GO
    
    -- Esse Insert deve funcionar 
    insert into Estados (Estado) values ('RS'), ('SP')
    
    -- Cria Tabela
    CREATE TABLE [dbo].[Clientes](
    	[Id] [int] IDENTITY(1,1) NOT NULL Primary Key,
    	[Nome] [varchar](50) NULL,
    	[idEstado] [int] NULL)
    go
    
    -- Cria a Function para Verificação
    create function [dbo].[VerificaEstado](@idEstado int)
    returns int
    as 
    begin
        -- VErifica se o estado existe na tabela de Estados
        return (select id from Estados where id = @idEstado) 
    end
    GO
    
    -- Implementa a Function
    ALTER TABLE [dbo].[Clientes]  WITH CHECK 
    ADD  CONSTRAINT [chk_VerificaEstado] 
    CHECK  (([dbo].[VerificaEstado]([idEstado]) IS NOT NULL))
    GO
    
    ALTER TABLE [dbo].[Clientes] 
    CHECK CONSTRAINT [chk_VerificaEstado]
    GO
    
    -- Esse Insert Deve Funcionar
    insert into Clientes (Nome, idEstado) values ('Roberto Fonseca', 1)
    -- Esse Insert Tem que dar Erro de Constrant de Check Violada
    insert into Clientes (Nome, idEstado) values ('Tem que Dar Erro', 3)
    
    select * from Clientes
    
    use master
    go
    drop database exemplo
    go
    


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008

    • Marcado como Resposta Douglas Canto segunda-feira, 22 de dezembro de 2014 14:18
    segunda-feira, 22 de dezembro de 2014 13:49
    Moderador

Todas as Respostas

  • Douglas,

    É possível, você vai precisar definir a trigger para disparar no INSERT e retornar uma mensagem (se necessário) para o usuário. Segue um exemplo para você adaptar à sua necessidade:

    CREATE TRIGGER TI_SuaTrigger ON SuaTabela
    AFTER INSERT
    AS
    
    IF EXISTS(SELECT 1 FROM SuaOutraTabela AS OT 
        INNER JOIN inserted AS I on I.CD_PESSOA = OT.CD_PESSOA)
      BEGIN
        rollback
        RAISERROR ('Registros Duplicados !', 16, 1);
      END
    GO

    Para maiores informações veja:

    http://msdn.microsoft.com/pt-br/library/ms189799.aspx

    Se ajudou na sua solução, não esqueça de marcar como resposta !

    Abraços,

    Durval Ramos
    Microsoft Partner | MTA | MCSA - SQL Server 2012 | MCSE - Data Platform
    ----------------------------------
    Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"

    segunda-feira, 22 de dezembro de 2014 11:56
    Moderador
  • Douglas,

    Você pode criar uma trigger de INSTEAD OF INSERT

    O código que colocar nessa trigger será executado "ao invés de inserir", ou seja, ao invés de inserir o registro, seu código de verificação dos valores na outra tabela será executado.

    Lembre-se que você deverá fazer o insert manualmente dentro da trigger caso seu registro seja válido. Se você não fizer o código do insert, seus registros nunca serão gravados nessa tabela.

    http://technet.microsoft.com/pt-br/library/ms175521(v=sql.105).aspx

    E lembre-se também que triggers sempre oneram o sistema. Se for uma tabela que recebe muitos inserts, você deve repensar o uso da trigger, pois a cada registro inserido todo o código escrito por você será executado.

    Espero ter ajudado.


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    segunda-feira, 22 de dezembro de 2014 11:59
  • Deleted
    segunda-feira, 22 de dezembro de 2014 12:54
  • Douglas, 

         Pelo cenário que você citou, porque você não utiliza uma Constraint de Check?? Ela faz exatamente o que você está querendo!

         Por default a constraint de check não verifica dados em outras tabelas, mas é possível validar criando uma function. Criei um exemplo que cria uma constraint de check que verifica se o estado existe antes de inserir os dados na tabela de clientes. Veja se pode ajudá-lo:

    USE [master]
    GO
    CREATE DATABASE [Exemplo] 
    go
    
    USE [Exemplo]
    GO
    -- Cria a Tabela de Relacionamento a ser Verificada
    CREATE TABLE [dbo].[Estados](
    	[id] [int] IDENTITY(1,1) NOT NULL Primary Key,
    	[Estado] [char](2) NULL)
    GO
    
    -- Esse Insert deve funcionar 
    insert into Estados (Estado) values ('RS'), ('SP')
    
    -- Cria Tabela
    CREATE TABLE [dbo].[Clientes](
    	[Id] [int] IDENTITY(1,1) NOT NULL Primary Key,
    	[Nome] [varchar](50) NULL,
    	[idEstado] [int] NULL)
    go
    
    -- Cria a Function para Verificação
    create function [dbo].[VerificaEstado](@idEstado int)
    returns int
    as 
    begin
        -- VErifica se o estado existe na tabela de Estados
        return (select id from Estados where id = @idEstado) 
    end
    GO
    
    -- Implementa a Function
    ALTER TABLE [dbo].[Clientes]  WITH CHECK 
    ADD  CONSTRAINT [chk_VerificaEstado] 
    CHECK  (([dbo].[VerificaEstado]([idEstado]) IS NOT NULL))
    GO
    
    ALTER TABLE [dbo].[Clientes] 
    CHECK CONSTRAINT [chk_VerificaEstado]
    GO
    
    -- Esse Insert Deve Funcionar
    insert into Clientes (Nome, idEstado) values ('Roberto Fonseca', 1)
    -- Esse Insert Tem que dar Erro de Constrant de Check Violada
    insert into Clientes (Nome, idEstado) values ('Tem que Dar Erro', 3)
    
    select * from Clientes
    
    use master
    go
    drop database exemplo
    go
    


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008

    • Marcado como Resposta Douglas Canto segunda-feira, 22 de dezembro de 2014 14:18
    segunda-feira, 22 de dezembro de 2014 13:49
    Moderador
  •  Muito obrigado Roberto.

    Funcionou corretamente.

    segunda-feira, 22 de dezembro de 2014 14:18