触发器上的多行更新

时间:2014-01-29 18:52:43

标签: sql-server triggers cursor

所以小伙子们,我已经采取了预先设定的触发器并尝试在其上添加光标,因此它将逐行更新,不知何故我的光标进入循环......我是新手SQL语言仍然有很多疑问......我想知道这里是否有人可以帮助我...这里是代码:

ALTER TRIGGER TGFUNALTGROUP ON PFUNFPTO
FOR UPDATE
AS
set xact_abort on
DECLARE
   @PESS_ID                     NUMERIC(19),
   @PESS_NOME                   VARCHAR(100),
   @PESS_NOMEANTIGO             VARCHAR(100),
   @PESS_NOMEABREVIADO          VARCHAR(50),
   @PESS_NOMEABREVIADOANTIGO    VARCHAR(50),
   @MATR_ID                     NUMERIC(19),
   @MATR_MATRICULA              VARCHAR(30),
   @MATR_TELEFONE               VARCHAR(20),
   @MATR_TELEFONEANTIGO         VARCHAR(20),
   @MATR_RAMALPRINCIPAL         VARCHAR(10),
   @MATR_RAMALPRINCIPALANTIGO   VARCHAR(10),
   @MATR_RAMALSECUNDARIO        VARCHAR(10),
   @MATR_RAMALSECUNDARIOANTIGO  VARCHAR(10),
   @MATR_FUNCAO                 VARCHAR(50),
   @MATR_FUNCAOANTIGO           VARCHAR(50),
   @MATR_ATIVO                  VARCHAR(1),
   @EMPR_ID                     NUMERIC(6),
   @LOTA_ID                     NUMERIC(6),
   @CTRF_ID                     NUMERIC(6),
   @DFFUNDATADEMISSAO           DATETIME,
   @DFFUNDATADEMISSAOANTIGO     DATETIME,
   @DFEMPCODIGO                 VARCHAR(5),
   @DFORGCODIGO                 VARCHAR(20),
   @DFEMPCODIGOANTIGO           VARCHAR(5),
   @DFORGCODIGOANTIGO           VARCHAR(20),
   @DFCTRCODIGO                 VARCHAR(2),
   @DFCTRCODIGOANTIGO           VARCHAR(2)
  BEGIN

-- Carrega os dados alterados
DECLARE c_UPDATE CURSOR
    FAST_FORWARD
    FOR
   SELECT DFFUNNOME,
          DFFUNABREVIADO,
          RTRIM(CONVERT(VARCHAR(15),CONVERT(NUMERIC(15),DFFUNCRACHA))),
          DFFUNTELEFONE,
          DFFUNRAMALPRI,
          DFFUNRAMALSEC,
          DFFUNFUNCAO,
          DFFUNATIVO,
          DFFUNDATADEMISSAO,
          DFEMPCODIGO,
         DFORGCODIGO,
         DFCTRCODIGO
    FROM INSERTED
 OPEN c_UPDATE
FETCH NEXT FROM c_UPDATE INTO 
          @PESS_NOME,
          @PESS_NOMEABREVIADO,
          @MATR_MATRICULA,
          @MATR_TELEFONE,
          @MATR_RAMALPRINCIPAL,
          @MATR_RAMALSECUNDARIO,
          @MATR_FUNCAO,
          @MATR_ATIVO,
         @DFFUNDATADEMISSAO,
         @DFEMPCODIGO,
          @DFORGCODIGO,
          @DFCTRCODIGO

DECLARE c_UPDATED CURSOR
    FAST_FORWARD
    FOR
SELECT DFFUNNOME,
       DFFUNABREVIADO,
       DFFUNTELEFONE,
      DFFUNRAMALPRI,
       DFFUNRAMALSEC,
       DFFUNFUNCAO,
       DFFUNDATADEMISSAO,
      DFEMPCODIGO,
       DFORGCODIGO,
       DFCTRCODIGO
   FROM DELETED
 OPEN c_UPDATED
FETCH NEXT FROM c_UPDATED INTO
@PESS_NOMEANTIGO,
@PESS_NOMEABREVIADOANTIGO,
@MATR_TELEFONEANTIGO,
@MATR_RAMALPRINCIPALANTIGO,
@MATR_RAMALSECUNDARIOANTIGO,
@MATR_FUNCAOANTIGO,
@DFFUNDATADEMISSAOANTIGO,
@DFEMPCODIGOANTIGO,
@DFORGCODIGOANTIGO,
@DFCTRCODIGOANTIGO
WHILE @@FETCH_STATUS <> -1  
-- Verifica se alterou alguma informação integrada
BEGIN
    IF @PESS_NOMEANTIGO<>@PESS_NOME
OR @PESS_NOMEABREVIADOANTIGO <> @PESS_NOMEABREVIADO
OR @MATR_TELEFONEANTIGO <> @MATR_TELEFONE
OR @MATR_RAMALPRINCIPALANTIGO <> @MATR_RAMALPRINCIPAL
OR @MATR_RAMALSECUNDARIOANTIGO <> @MATR_RAMALSECUNDARIO
OR @DFFUNDATADEMISSAOANTIGO <> @DFFUNDATADEMISSAO
OR @DFEMPCODIGOANTIGO <> @DFEMPCODIGO
OR @DFORGCODIGOANTIGO <> @DFORGCODIGO
OR @DFCTRCODIGOANTIGO <> @DFCTRCODIGO
BEGIN
-- Determina o id do Matriculado
   SET    @MATR_ID = 0
   SET    @PESS_ID = 0
   SELECT @MATR_ID = MATR_ID, @PESS_ID = PESS_ID
   FROM   MATRICULADO
   WHERE  EMPR_GRUPO = 1
   AND    MATR_MATRICULA = @MATR_MATRICULA

-- Converte valores
   IF @DFFUNDATADEMISSAO = '1899-30-12' --CONVERT(DATETIME,'30/12/1899',101)
      SET @MATR_ATIVO = '1'
   ELSE
      SET @MATR_ATIVO = '0'

-- Se encontrou o Matriculado atualiza os dados
   IF @MATR_ID <> 0 AND @PESS_ID <> 0

   BEGIN
      UPDATE PESSOA SET
      PESS_NOME = @PESS_NOME,
      PESS_NOMEABREVIADO = @PESS_NOMEABREVIADO,
      PESS_NOMEFONETICO = @PESS_NOME
      WHERE PESS_ID = @PESS_ID

      UPDATE MATRICULADO SET
      MATR_TELEFONE = @MATR_TELEFONE,
      MATR_RAMALPRINCIPAL = @MATR_RAMALPRINCIPAL,
      MATR_RAMALSECUNDARIO = @MATR_RAMALSECUNDARIO,
      MATR_FUNCAO = @MATR_FUNCAO,
      MATR_ATIVO = @MATR_ATIVO
      WHERE MATR_ID = @MATR_ID

      -- Se mudou os dados de empresa e orgão gera uma nova alocação
      IF @DFEMPCODIGO <> @DFEMPCODIGOANTIGO OR @DFORGCODIGO <>     @DFORGCODIGOANTIGO
      BEGIN 
          -- Verifica se a empresa e orgão do Forponto existem no Foracesso
          SET @LOTA_ID = 0;
          SET @EMPR_ID = 0;

          SELECT @LOTA_ID = LOTA_ID 
          FROM LOTACAO
          WHERE LOTA_SIGLA = @DFORGCODIGO

          SELECT @EMPR_ID = EMPR_ID
          FROM EMPRESA
          WHERE EMPR_CODIGO = @DFEMPCODIGO

          IF @LOTA_ID <> 0 AND @EMPR_ID <> 0
          BEGIN
             -- limpa os registros de alocação posteriores a data atual
             DELETE FROM MATRICULADO_ALOCACAO
             WHERE MATR_ID = @MATR_ID
             AND   MAAL_INICIO >=     CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
             -- Encerra a alocação atual
             UPDATE MATRICULADO_ALOCACAO
             SET MAAL_TERMINO =    DATEADD(mi,-1,CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101))
             WHERE MATR_ID = @MATR_ID
             AND   MAAL_INICIO <    CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
             AND   (MAAL_TERMINO >=    CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
             OR    MAAL_TERMINO IS NULL
             )
             -- Inclui a nova alocação
             INSERT INTO MATRICULADO_ALOCACAO
             (MATR_ID, MAAL_INICIO, LOTA_ID, EMPR_ID) VALUES
             (@MATR_ID,    CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101),@LOTA_ID, @EMPR_ID)
          END
      END
      -- Se mudou os dados de categoria de refeição gera uma nova associação
      IF @DFCTRCODIGO <> @DFCTRCODIGOANTIGO
      BEGIN
        -- limpa os registros de categoria refeição posteriores a data atual
        DELETE FROM MATRICULADO_CATEG_REFEICAO
        WHERE MATR_ID = @MATR_ID
        AND   MACT_INICIO >=     CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
        -- Encerra a alocação atual
        UPDATE MATRICULADO_CATEG_REFEICAO
        SET MACT_TERMINO = DATEADD(mi,-1,CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101))
        WHERE MATR_ID = @MATR_ID
        AND   MACT_INICIO < CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
        AND   (MACT_TERMINO >= CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101)
        OR    MACT_TERMINO IS NULL)

        -- -- Inclui a nova alocação
        SET @CTRF_ID = 0

        SELECT @CTRF_ID = CTRF_ID
        FROM CATEGORIA_REFEICAO
        WHERE CTRF_DESCRICAO = ( SELECT UPPER(DFCTRDESCRICAO) FROM PCTRFPTO WHERE DFCTRCODIGO = @DFCTRCODIGO)

        IF (@CTRF_ID <> 0) 
        BEGIN
            INSERT INTO MATRICULADO_CATEG_REFEICAO
            (MATR_ID, CTRF_ID, MACT_INICIO) VALUES
            (@MATR_ID,   @CTRF_ID,CONVERT(DATETIME,CONVERT(VARCHAR(10),GETDATE(),101),101))
        END
      END
   END

END   
END
END
CLOSE c_UPDATE
CLOSE c_UPDATED
DEALLOCATE c_UPDATE 
DEALLOCATE c_UPDATED     

2 个答案:

答案 0 :(得分:0)

你需要在WHILE循环中有另一个FETCH NEXT语句来获取下一行。否则@@ FETCH_STATUS永远不会改变,你将永远陷入循环中。

答案 1 :(得分:0)

光标是邪恶使用而不是CROSS APPLY,不要将基于集合的技术用于基于非集合的功能。

以下是如何应用它的链接:

http://www.codeproject.com/Tips/654894/How-to-Use-Cross-Apply-Instead-of-Cursors-in-SQL-S