none
TRIGGER e Procedure instrução DML não pode ter gatilhos habilitados se a instrução contém uma cláusula OUTPUT sem cláusula INTO. RRS feed

  • Pergunta

  • Boa noite!

    Estou com uma situação, tenho uma tabela chamada

    alm_entrada_produto_item a qual é inserida pela procedure [prc_ALM_InsertEntradaProdutoItem]           

    ALTER PROCEDURE [prc_ALM_InsertEntradaProdutoItem]
       @p_id_entidade int,
       @p_id_entrada_produto_item int,
       @p_id_entrada_produto_itemSaida int OUTPUT,
       @p_id_produto int,
       @p_qtde_produto int,
       @p_valor_unitario decimal(10, 2),
       @p_data_validade datetime,
       @p_numero_lote nvarchar(45),
       @p_id_entrada_produto int,
       @p_id_almoxarifado int,
       @p_observacao_entrada varchar(3000),
       @p_tipo_entrada varchar(45),
       @p_id_transferencia int,
       @p_id_estorno int
    AS 

    BEGIN TRANSACTION
       BEGIN try
          DECLARE
             @contador int

          SELECT @contador = count_big(*)
          FROM dbo.alm_entrada_produto_item
          WHERE (id_entidade=@p_id_entidade) and alm_entrada_produto_item.id_entrada_produto_item = @p_id_entrada_produto_item

          IF @contador > 0
             UPDATE dbo.alm_entrada_produto_item
                SET 
    id_produto = @p_id_produto, 
                   qtde_produto = @p_qtde_produto, 
                   valor_unitario = @p_valor_unitario, 
                   data_validade = @p_data_validade, 
                   numero_lote = @p_numero_lote, 
                   id_almoxarifado = @p_id_almoxarifado, 
                   observacao_entrada = @p_observacao_entrada, 
                   tipo_entrada = @p_tipo_entrada

          WHERE (id_entidade=@p_id_entidade) and alm_entrada_produto_item.id_entrada_produto_item = @p_id_entrada_produto_item
          ELSE 
             BEGIN

                 INSERT dbo.alm_entrada_produto_item(
    id_entidade,
                id_produto, 
                qtde_produto, 
                valor_unitario, 
                data_validade, 
                numero_lote, 
                id_entrada_produto, 
                id_almoxarifado, 
                observacao_entrada, 
                tipo_entrada, 
                id_transferencia, 
                id_estorno)
                VALUES (
    @p_id_entidade,
                   @p_id_produto, 
                   @p_qtde_produto, 
                   @p_valor_unitario, 
                   @p_data_validade, 
                   @p_numero_lote, 
                   @p_id_entrada_produto, 
                   @p_id_almoxarifado, 
                   @p_observacao_entrada, 
                   @p_tipo_entrada, 
                   @p_id_transferencia, 
                   @p_id_estorno)
             END
         COMMIT TRANSACTION -- Efetivando alterações na base
             SET @p_id_entrada_produto_itemSaida=SCOPE_IDENTITY()
    return @p_id_entrada_produto_itemSaida
       END try
       BEGIN CATCH

        PRINT ERROR_MESSAGE()
        ROLLBACK TRANSACTION -- Desfazendo as alterações na base

    END CATCH

    ----------------------------------

    e a Tabela alm_entrada_produto_item contém um trigger que atualiza o saldo do estoque na tabela

     

    alter TRIGGER [tr_ObterIDAlmAtualizarSaldoEstoque]
    ON [dbo].[alm_entrada_produto_item]
    AFTER INSERT AS

    DECLARE
       @p_id_entidade int

    SELECT @p_id_entidade  = (select top 1 id_entidade FROM inserted)

    IF (@p_id_entidade is null)
    begin
        RAISERROR ('Informe a entidade antes de prosseguir', 11,1);
    Rollback;
    end
    ELSE
    begin

    EXECUTE prc_ALM_AtualizarEstoque 
    SELECT
    id_entidade, 
                id_entrada_produto,
                id_produto, 
                qtde_produto, 
                id_almoxarifado, 
                valor_unitario, 
                data_validade, 
                numero_lote
    FROM INSERTED
    END

    que por sua vez chama a procedure prc_ALM_AtualizarEstoque  para atualizar o saldo

       

    ALTER PROCEDURE prc_ALM_AtualizarEstoque  
       @p_id_entidade int,
       @p_id_entrada_produto int,
       @p_id_produto int,
       @p_qtde_produto int,
       @p_id_almoxarifado int,
       @p_valor_unitario decimal(10, 2),
       @p_data_validade datetime,
       @p_numero_lote nvarchar(45)
    AS 
       BEGIN
          DECLARE
             @contador int

          SELECT @contador = count_big(*)
          FROM alm_estoque
          WHERE 
      (id_entidade=@p_id_entidade) AND
             id_produto = @p_id_produto AND 
             id_almoxarifado = @p_id_almoxarifado AND 
             numero_lote = @p_numero_lote AND 
             data_validade = @p_data_validade AND 
             id_entrada_produto = @p_id_entrada_produto

          IF @contador > 0
      begin
             UPDATE alm_estoque
                SET 
                   qtde_produto = qtde_produto + @p_qtde_produto, 
                   id_almoxarifado = @p_id_almoxarifado
             WHERE (id_entidade=@p_id_entidade) AND
                id_produto = @p_id_produto AND 
                id_almoxarifado = @p_id_almoxarifado AND 
                numero_lote = @p_numero_lote AND 
                data_validade = @p_data_validade AND 
                id_entrada_produto = @p_id_entrada_produto
          end
      ELSE
      begin 
             INSERT dbo.alm_estoque(
        id_entidade, 
                id_entrada_produto,
                id_produto, 
                qtde_produto, 
                id_almoxarifado, 
                valor_unitario, 
                data_validade, 
                numero_lote)
                VALUES (
       @p_id_entidade, 
                   @p_id_entrada_produto,
                   @p_id_produto, 
                   @p_qtde_produto, 
                   @p_id_almoxarifado, 
                   @p_valor_unitario, 
                   @p_data_validade, 
                   @p_numero_lote)
       end
       END

    Porém quando tento incluir na tabela alm_entrada_produto_item me aparece essa mensagem

    A tabela de destino 'alm_entrada_produto_item' da instrução DML não pode ter gatilhos habilitados se a instrução contém uma cláusula OUTPUT sem cláusula INTO.

    Já tentei de todas as formas, se alguém puder me ajudar, agradeço.


    • Editado Elton07 domingo, 4 de agosto de 2019 22:59 MAIS LEGÍVEL.
    domingo, 4 de agosto de 2019 22:57

Respostas

  • Deleted
    • Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:56
    segunda-feira, 5 de agosto de 2019 09:01
  • Eu tenho uma outra trigger vinculada a tabela entrada_produto_item que basicamente, faz o seguinte, minha chave tá como autoincremento e tenho um campo chamado num_entrada_produto que por essa trigger eu obtenho o valor do último inserido e insiro mais um nesse campo, abaixo o código dela.

    ALTER TRIGGER [dbo].[tr_ObterIDAlmEntradaProduto_item]
    ON [dbo].[alm_entrada_produto_item]
    INSTEAD OF INSERT AS

    begin

    DECLARE
       @p_id_entidade int,
       @p_idSequencial int

    SET @p_id_entidade  = (select TOP 1 id_entidade FROM inserted)
    SET @p_idSequencial =(SELECT max(t.num_entrada_produto_item) from alm_entrada_produto_item t inner join inserted on t.id_entidade= inserted.id_entidade and t.id_entrada_produto=inserted.id_entrada_produto)

    IF (@p_id_entidade is null)
    begin
        RAISERROR ('Informe a entidade antes de prosseguir', 11,1);
    Rollback;
    end
    ELSE
    begin
    if ((@p_idSequencial <= 0) or (@p_idSequencial is null))
       begin
       set @p_idSequencial = 1
       end
      else
       begin
      set @p_idSequencial = @p_idSequencial + 1
       end

     INSERT alm_entrada_produto_item(   
    id_entidade
    ,num_entrada_produto_item
                ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno)
                   OUTPUT INSERTED.id_entrada_produto_item
            select 
       id_entidade
       ,@p_idSequencial
      ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno
      from inserted

    END
    end

    Elton,

    Olha no seu código a clausula Output!

    Se a coluna é autonumerada no insert da mesma tabela você não precisa passar valores, mas caso deseje via Output direcionar o resultado para outra tabela ou apresentar em tela, neste caso, esta coluna autonumerada poderá ser utilizada.

    Seria possível desativar esta Trigger para testarmos?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:57
    segunda-feira, 5 de agosto de 2019 15:06
  • Elton,

    Que bom, fico feliz que tenhamos ajudado.

    Em relação ao Sequence na verdade você vai criar um objeto sequenciador de forma geral, a não ser que você pense em criar mais de um sequence, cada um vinculado a sua específica tabela, veja o exemplo abaixo apresentado pela documentação Microsoft:

    https://docs.microsoft.com/pt-br/sql/relational-databases/sequence-numbers/sequence-numbers?view=sql-server-2017#a-using-a-sequence-number-in-a-single-table

    --Create the Test schema  
    CREATE SCHEMA Test ;  
    GO  
      
    -- Create a table  
    CREATE TABLE Test.Orders  
        (OrderID int PRIMARY KEY,  
        Name varchar(20) NOT NULL,  
        Qty int NOT NULL);  
    GO  
      
    -- Create a sequence  
    CREATE SEQUENCE Test.CountBy1  
        START WITH 1  
        INCREMENT BY 1 ;  
    GO  
      
    -- Insert three records  
    INSERT Test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Tire', 2) ;  
    INSERT test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Seat', 1) ;  
    INSERT test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Brake', 1) ;  
    GO  
      
    -- View the table  
    SELECT * FROM Test.Orders ;  
    GO

    Demais links úteis:

    CREATE SEQUENCE (Transact-SQL)

    ALTER SEQUENCE (Transact-SQL)

    DROP SEQUENCE (Transact-SQL)



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 terça-feira, 6 de agosto de 2019 14:16
    terça-feira, 6 de agosto de 2019 01:35
  • Deleted
    • Marcado como Resposta Elton07 terça-feira, 6 de agosto de 2019 14:14
    terça-feira, 6 de agosto de 2019 09:17
  • Eu vou estudar mais o Sequence e como vou poder implementar, realmente eu vejo que além de mais performático é mais prático do que o método que eu estou usando hoje.

    Agora tudo ficou mais fácil KKK.

    Elton,

    Ok, espero que você consiga, depois retorne nos informando se deu tudo certo.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 terça-feira, 31 de dezembro de 2019 14:43
    terça-feira, 6 de agosto de 2019 14:21

Todas as Respostas

  • Deleted
    • Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:56
    segunda-feira, 5 de agosto de 2019 09:01
  • Deleted
    segunda-feira, 5 de agosto de 2019 10:05
  • Elton,

    Aparentemente a ordem de execução definida para todo este processo é esta:

    1. alm_entrada_produto_item a qual é inserida pela procedure [prc_ALM_InsertEntradaProdutoItem];
    2. alm_entrada_produto_item também possui um Trigger, que atualiza o saldo do estado na mesma tabela; e
    3. Alm_entrada_produto_item e depois chama a prc_ALM_AtualizarEstoque atualiza o Saldo da tabela ALM_Estoque.

    É isso mesmo?

    Parece-me que existe uma redundância na execução! Por gentileza, você poderia desativar inicialmente a trigger?

    Além das sugestões apresentadas anteriormente sobre o uso de Trigger, gostaria de destacar também, caso queria saber mais sobre como construir Triggers que levam em consideração a análise e abordagem do processamento de multiplas linhas, além do link apresentado anteriormente, recomendo caso necessário o acesso ao link da documentação oficial da Microsoft Brasil: Crie gatilhos DML para tratar várias linhas de dados.

    Além disso, toda documentação oficial Microsoft no que se refere ao SQL Server e Azure esta sendo construída, escrita, reescrita e mantida por nós MVPs de Data Platform localizados em diversos países do mundo, algo que não representa ser 100% correto ou infalível, estamos em constante melhorias e correções.

    Outro link muito útil e que lhe poderá ajudar, relaciona-se ao próprio conceito de Gatilhos DML.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 10:42
  • Bom dia José!

    Testei a instrução que você me sugeriu e alterei a trigger para ficar como dito, porém o mesmo erro é informado, estou tentando inserir pela procedure 

    EXECUTE [prc_ALM_InsertEntradaProdutoItem]
    1,0,0,5,100,'0.90',null,null,54,23,null,'e',null,null

     

    Abaixo o retorno, quando eu desabilito a trigger [tr_ObterIDAlmAtualizarSaldoEstoque] o insert acima funciona.

    (0 linha(s) afetadas)
    A tabela de destino 'alm_entrada_produto_item' da instrução DML não pode ter gatilhos habilitados se a instrução contém uma cláusula OUTPUT sem cláusula INTO.

    Obrigado pela ajuda , fico no aguardo da resposta.

    segunda-feira, 5 de agosto de 2019 14:24
  • Bom dia José!

    Irei efetuar essa alteração, essa seria mais performática?

    Att

    segunda-feira, 5 de agosto de 2019 14:24
  • Bom dia Junior!

    A lógica criada é a seguinte, eu faço a inclusão chamando a procedure [prc_ALM_InsertEntradaProdutoItem] ao inserir na tabela EntradaProdutoItem disparo a trigger que verifica o que foi incluído e atualiza os quantitativos e valores de outra tabela chamada estoque através da procedure prc_ALM_AtualizarEstoque.

    Ordem

    1 - Procedure [prc_ALM_InsertEntradaProdutoItem]

    2 - Após Inclusão chamo a Trigger [tr_ObterIDAlmAtualizarSaldoEstoque] que dentro dela executa uma outra procedure chamada [prc_ALM_AtualizarEstoque].

    segunda-feira, 5 de agosto de 2019 14:28
  • Elton,

    Ok, obrigado pelo esclarecimento, vamos por partes então:

    - Se você desativou o Trigger tr_ObterIDAlmAtualizarSaldoEstoque o insert acontece, então o problema esta justamente na passado dos dados dentro da sua Stored Procedure: prc_ALM_InsertEntradaProdutoItem

    Existe a possibilidade de fazermos um teste, remover a chamada da Stored Procedure dentro da trigger e verifique se algum erro é apresentado.

    Verifique os blocos de comando Insert que você esta utilizando tanto no trigger, como principalmente em suas stored procedures.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 14:38
  • Deleted
    segunda-feira, 5 de agosto de 2019 14:43
  • Eu comentei a chamada da Procedure dentro da trigger 

    ALTER TRIGGER [dbo].[tr_ObterIDAlmAtualizarSaldoEstoque]
    ON [dbo].[alm_entrada_produto_item]
    AFTER INSERT AS
    -- chama procedimento de atualização de estoque
    declare @p_id_entidade int,
            @p_id_entrada_produto int,
            @p_id_produto int,
            @p_qtde_produto int,
            @p_id_almoxarifado int,
            @p_valor_unitario decimal(10,2),
            @p_data_validade datetime,
            @p_numero_lote nvarchar(45);

    SELECT @p_id_entidade= id_entidade,
           @p_id_entrada_produto= id_entrada_produto,
           @p_id_produto= id_produto,
           @p_qtde_produto= qtde_produto,
           @p_id_almoxarifado= id_almoxarifado,
           @p_valor_unitario= valor_unitario,
           @p_data_validade= data_validade,
           @p_numero_lote= numero_lote
      from INSERTED;

    IF (@p_id_entidade is null)
    begin
        RAISERROR ('Informe a entidade antes de prosseguir', 11,1);
    Rollback;
    end
    ELSE
    begin

    PRINT 'OK'
     
    --EXECUTE prc_ALM_AtualizarEstoque 
    -- @p_id_entidade, @p_id_entrada_produto, @p_id_produto,@p_qtde_produto, @p_id_almoxarifado, @p_valor_unitario,@p_data_validade, @p_numero_lote;
    END

    Porém o erro ainda persiste.

    segunda-feira, 5 de agosto de 2019 14:44
  • Elton,

    Então, já identificamos que o erro não esta no [tr_ObterIDAlmAtualizarSaldoEstoque] e na Stored Procedure prc_ALM_AtualizarEstoque.

    Você tem certeza que não existe nenhum outro trigger?

    Temos agora que verificar o código da outra Stored Procedure prc_ALM_InsertEntradaProdutoItem.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 14:58
  • Eu tenho uma outra trigger vinculada a tabela entrada_produto_item que basicamente, faz o seguinte, minha chave tá como autoincremento e tenho um campo chamado num_entrada_produto que por essa trigger eu obtenho o valor do último inserido e insiro mais um nesse campo, abaixo o código dela.

    ALTER TRIGGER [dbo].[tr_ObterIDAlmEntradaProduto_item]
    ON [dbo].[alm_entrada_produto_item]
    INSTEAD OF INSERT AS

    begin

    DECLARE
       @p_id_entidade int,
       @p_idSequencial int

    SET @p_id_entidade  = (select TOP 1 id_entidade FROM inserted)
    SET @p_idSequencial =(SELECT max(t.num_entrada_produto_item) from alm_entrada_produto_item t inner join inserted on t.id_entidade= inserted.id_entidade and t.id_entrada_produto=inserted.id_entrada_produto)

    IF (@p_id_entidade is null)
    begin
        RAISERROR ('Informe a entidade antes de prosseguir', 11,1);
    Rollback;
    end
    ELSE
    begin
    if ((@p_idSequencial <= 0) or (@p_idSequencial is null))
       begin
       set @p_idSequencial = 1
       end
      else
       begin
      set @p_idSequencial = @p_idSequencial + 1
       end

     INSERT alm_entrada_produto_item(   
    id_entidade
    ,num_entrada_produto_item
                ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno)
                   OUTPUT INSERTED.id_entrada_produto_item
            select 
       id_entidade
       ,@p_idSequencial
      ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno
      from inserted

    END
    end

    segunda-feira, 5 de agosto de 2019 15:02
  • Eu tenho uma outra trigger vinculada a tabela entrada_produto_item que basicamente, faz o seguinte, minha chave tá como autoincremento e tenho um campo chamado num_entrada_produto que por essa trigger eu obtenho o valor do último inserido e insiro mais um nesse campo, abaixo o código dela.

    ALTER TRIGGER [dbo].[tr_ObterIDAlmEntradaProduto_item]
    ON [dbo].[alm_entrada_produto_item]
    INSTEAD OF INSERT AS

    begin

    DECLARE
       @p_id_entidade int,
       @p_idSequencial int

    SET @p_id_entidade  = (select TOP 1 id_entidade FROM inserted)
    SET @p_idSequencial =(SELECT max(t.num_entrada_produto_item) from alm_entrada_produto_item t inner join inserted on t.id_entidade= inserted.id_entidade and t.id_entrada_produto=inserted.id_entrada_produto)

    IF (@p_id_entidade is null)
    begin
        RAISERROR ('Informe a entidade antes de prosseguir', 11,1);
    Rollback;
    end
    ELSE
    begin
    if ((@p_idSequencial <= 0) or (@p_idSequencial is null))
       begin
       set @p_idSequencial = 1
       end
      else
       begin
      set @p_idSequencial = @p_idSequencial + 1
       end

     INSERT alm_entrada_produto_item(   
    id_entidade
    ,num_entrada_produto_item
                ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno)
                   OUTPUT INSERTED.id_entrada_produto_item
            select 
       id_entidade
       ,@p_idSequencial
      ,id_produto
                ,qtde_produto 
                ,valor_unitario 
                ,data_validade 
                ,numero_lote
                ,id_entrada_produto 
                ,id_almoxarifado
                ,observacao_entrada 
                ,tipo_entrada
                ,id_transferencia 
                ,id_estorno
      from inserted

    END
    end

    Elton,

    Olha no seu código a clausula Output!

    Se a coluna é autonumerada no insert da mesma tabela você não precisa passar valores, mas caso deseje via Output direcionar o resultado para outra tabela ou apresentar em tela, neste caso, esta coluna autonumerada poderá ser utilizada.

    Seria possível desativar esta Trigger para testarmos?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:57
    segunda-feira, 5 de agosto de 2019 15:06
  • Deleted
    segunda-feira, 5 de agosto de 2019 15:10
  • Elton,

    Outra observação que gostaria de expor, em relação ao Count_Big(), se o seu tipo de dados é Int, então utilize somente a função Count(), o count_big é utilizado quando o tipo de dados que armazena o valor for BigInt. 

    Isso é evidenciado na documentação da Microsoft.

    BEGIN TRANSACTION

       BEGIN try
          DECLARE
             @contador int

          SELECT @contador = count_big(*)
          FROM dbo.alm_entrada_produto_item
          WHERE (id_entidade=@p_id_entidade) and alm_entrada_produto_item.id_entrada_produto_item = @p_id_entrada_produto_item


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 15:11
  • O banco que eu estava utilizando era o Mysql, ao por questão de praticidade acabei por optando converter toda a estrutura para o SQL Server, utilizei a ferramenta Microsoft SQL Server Migration Assistant for MySQL ai em alguns casos ele converteu int em count(*) em count_big(*) mas irei ajustar isso também, obrigado pelo feedback.
    segunda-feira, 5 de agosto de 2019 15:22
  • Junior, fiz o seguinte teste, fiz um DROP na trigger [tr_ObterIDAlmEntradaProduto_item] e tentei fazer a inclusão EXECUTE [prc_ALM_InsertEntradaProdutoItem]
    1,0,0,5,100,'0.90',null,null,54,23,null,'e',null,null

    E a inserção foi feita corretamente, agora quando tento criar novamente a trigger [tr_ObterIDAlmEntradaProduto_item] é informada a mensagem:

    Mensagem 334, Nível 16, Estado 1, Procedimento tr_ObterIDAlmEntradaProduto_item, Linha 39
    A tabela de destino 'alm_entrada_produto_item' da instrução DML não pode ter gatilhos habilitados se a instrução contém uma cláusula OUTPUT sem cláusula INTO.

    segunda-feira, 5 de agosto de 2019 15:25
  • José, é porque como o campo output eu verificava antes de inserir na tabela eu informei ela numa própria trigger na tabela.

    Agora bagunçou minha cabeça rs rs

    segunda-feira, 5 de agosto de 2019 15:27
  • Elton,

    Tem mais alguma coisa confusa nesta estrutura, se você apagou a trigger, como pode ele estar sendo chamado novamente.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 15:38
  • Junior eu fiz o seguinte fiz uns ajustes na trigger tr_ObterIDAlmEntradaProduto_item, e retirei a cláusula OUTPUT INSERTED.id_entrada_produto_item do insert funcionou.

    Código Anterior:

     INSERT alm_entrada_produto_item(   
    id_entidade
    ,num_entrada_produto_item
                ,id_produto
                ,qtde_produto 
               ......
                ,id_estorno)
                   OUTPUT INSERTED.id_entrada_produto_item
            select 
       id_entidade
       ,@p_idSequencial
      ,id_produto
                ,qtde_produto 
             ....
                ,id_estorno
      from inserted

    END

    Código Novo:

     INSERT INTO alm_entrada_produto_item(   
    id_entidade
    ,num_entrada_produto_item
                ,id_produto
                ,qtde_produto 
                 ...
                ,id_estorno)
                 
            select 
    @p_id_entidade
    ,@p_idSequencial
    ,@p_id_produto
                            ,@p_qtde_produto 
                              ....
                            ,@p_id_estorno
                 

    END

    Ai possibilitou a criação dela novamente, porém eu não consigo obter o valor do campo autoincremento do ID da tabela.

    segunda-feira, 5 de agosto de 2019 15:47
  • Deleted
    segunda-feira, 5 de agosto de 2019 16:00
  • José qual seria a melhor indicação no caso?

    No seguinte cenário:

    Tabela Empresa /Entidade - Chave Id_entidade

    Tabela Entrada_Produto - Chave Id_entrada_produto e além da chave tenho um campo Num_entrada_produto que é incrementado de acordo com a entidade. Exemplo:

    Tabela Entrada

    Id_entrada_produto | ID_entidade  | num_entrada_produto

    1                                   1                         1

    2                                   1                         2 

    3                                   2                         1

    4                                   1                         3    

    segunda-feira, 5 de agosto de 2019 16:07
  • Deleted
    • Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:55
    • Não Marcado como Resposta Elton07 segunda-feira, 5 de agosto de 2019 21:55
    segunda-feira, 5 de agosto de 2019 16:27
  • Elton,

    Obrigado pelo retorno, que bom que esta primeiro passo conseguimos identificar a causa.

    Pois bem, em relação ao Identity(), ele é bom e ao mesmo tempo ruim (kkkk), tudo vai depender da maneira e forma de implementação.

    Quando utilizamos este recurso o SQL Server nos oferece algumas funcionalidades que podem ser utilizadas em conjunto, dentro elas a mais conhecida que é a variável @@Identity, temos outras:

    IDENT_CURRENT (Transact-SQL)

    SCOPE_IDENTITY (Transact-SQL)

    Neste link você vai poder encontrar um exemplo de código que compara e apresenta as diferenças entre estas três funcionalidades:

    https://www.codeproject.com/Articles/103610/Difference-between-IDENTITY-SCOPE-IDENTITY-IDENT-C

    Se eu entendi, você tem a necessidade de obter o número do Identity para se reutilizado posteriormente, já pensou em utilizar um outro Trigger mas do tipo Instead Of:

    -- Criando a Tabela -- 
    Create Table TesteIdentity
    (Codigo Int Identity(1,1),
      Descricao Varchar(30) Not Null)
    Go
    
    -- Criando a Trigger do tipo Instead Of Insert --
    Create Trigger T_ObterValorIdentity
    On TesteIdentity
    Instead Of Insert
    AS
    BEGIN
    Set NoCount On
    
    DECLARE @Relacao TABLE
     (Codigo INT);
    
    INSERT TesteIdentity (Descricao)
     Output inserted.Codigo Into @Relacao
     SELECT Descricao  FROM inserted
    
     Select * From @Relacao
    End
    Go
    
    -- Inserindo --
    Insert Into TesteIdentity Values ('Pedro'), ('Antonio'),('Galvão'),('Junior')
    Go
    
    -- Validando --
    Select * From TesteIdentity
    Go

    Ou então arriscar fazendo uso de algumas das funcionalidades que eu citei anteriormente.

    Referências:

    http://www.sqlservertutorial.net/sql-server-triggers/sql-server-instead-of-trigger/

    https://www.tutorialgateway.org/instead-of-insert-triggers-in-sql-server/

    https://docs.microsoft.com/pt-br/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-2017


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 17:46
  • José muito obrigado!

    Irei ler com calma esse conteúdo que você passou agora para tentar implementar. Já favoreitei o site https://portosql.wordpress.com/contato/ vi que tem ótimos posts que poderão me ajudar ao longo desse redescobrimento de banco de dados. 

    Muito provavelmente ainda irei buscar o conhecimento dessa fonte que é a sua Experiência rs. Valeu!

    segunda-feira, 5 de agosto de 2019 21:54
  • KKKk, É meu velho, primeira etapa concluída com sucesso. Obrigado novamente!

    Em relação a trigger a ALTER TRIGGER [dbo].[tr_ObterIDAlmEntradaProduto_item]
    ON [dbo].[alm_entrada_produto_item]
    INSTEAD OF INSERT AS já fazia isso, ela antes de inserir olhava qual era a última numeração do campo  num_entrada e adicionava mais um. Pelo visto terei que desativar ela realmente. 

    Vou olhar também o conteúd que você indicou. 

    Obrigado novamente pela atenção e por compartilhar a sua experiência. Com certeza terei mais dúvidas kkkk

    segunda-feira, 5 de agosto de 2019 22:01
  • Elton,

    Ok, ficamos no aguardo, se for o caso pense na possibilidade de utilizar as outras técnicas destacadas, mas isso vai depender da sua necessidade.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 5 de agosto de 2019 23:56
  • Junior,

    Estou pensando na possibilidade do SEQUENCE, porém pelo que eu andei lendo eu não tenho como sequenciar por um campo específico, no meu caso por empresa, ou seja cada empresa ter o seu próprio sequence.

    Quanto a situação acima consegui resolver agora a noite, analisei cuidadosamente e seguir todas as dicas para colocar nas procedures e nas triggers e funcionou junto com a minha aplicação.

    Muito obrigado novamente!

    terça-feira, 6 de agosto de 2019 00:36
  • Elton,

    Que bom, fico feliz que tenhamos ajudado.

    Em relação ao Sequence na verdade você vai criar um objeto sequenciador de forma geral, a não ser que você pense em criar mais de um sequence, cada um vinculado a sua específica tabela, veja o exemplo abaixo apresentado pela documentação Microsoft:

    https://docs.microsoft.com/pt-br/sql/relational-databases/sequence-numbers/sequence-numbers?view=sql-server-2017#a-using-a-sequence-number-in-a-single-table

    --Create the Test schema  
    CREATE SCHEMA Test ;  
    GO  
      
    -- Create a table  
    CREATE TABLE Test.Orders  
        (OrderID int PRIMARY KEY,  
        Name varchar(20) NOT NULL,  
        Qty int NOT NULL);  
    GO  
      
    -- Create a sequence  
    CREATE SEQUENCE Test.CountBy1  
        START WITH 1  
        INCREMENT BY 1 ;  
    GO  
      
    -- Insert three records  
    INSERT Test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Tire', 2) ;  
    INSERT test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Seat', 1) ;  
    INSERT test.Orders (OrderID, Name, Qty)  
        VALUES (NEXT VALUE FOR Test.CountBy1, 'Brake', 1) ;  
    GO  
      
    -- View the table  
    SELECT * FROM Test.Orders ;  
    GO

    Demais links úteis:

    CREATE SEQUENCE (Transact-SQL)

    ALTER SEQUENCE (Transact-SQL)

    DROP SEQUENCE (Transact-SQL)



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 terça-feira, 6 de agosto de 2019 14:16
    terça-feira, 6 de agosto de 2019 01:35
  • Deleted
    • Marcado como Resposta Elton07 terça-feira, 6 de agosto de 2019 14:14
    terça-feira, 6 de agosto de 2019 09:17
  • Eu vou estudar mais o Sequence e como vou poder implementar, realmente eu vejo que além de mais performático é mais prático do que o método que eu estou usando hoje.

    Agora tudo ficou mais fácil KKK.

    terça-feira, 6 de agosto de 2019 14:16
  • José,

    Realmente, eu irei usar a opção do Sequence, vou estudar melhor sobre ela, porque me parece a melhor alternativa para a proposta do que eu pretendo implementar.

    Obrigado! 

    terça-feira, 6 de agosto de 2019 14:18
  • Eu vou estudar mais o Sequence e como vou poder implementar, realmente eu vejo que além de mais performático é mais prático do que o método que eu estou usando hoje.

    Agora tudo ficou mais fácil KKK.

    Elton,

    Ok, espero que você consiga, depois retorne nos informando se deu tudo certo.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Elton07 terça-feira, 31 de dezembro de 2019 14:43
    terça-feira, 6 de agosto de 2019 14:21
  • Bom dia!

    Apenas retornando, deu tudo certo sim,

    Obrigado a todos.

    Abraço, 

    terça-feira, 31 de dezembro de 2019 14:43
  • Bom dia!

    Apenas retornando, deu tudo certo sim,

    Obrigado a todos.

    Abraço, 

    Elton007,

    Obrigado pelo retorno.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    quinta-feira, 2 de janeiro de 2020 15:39