Vin*_*oni 3 trigger sql-server-2005 sql-server
当我更新单行时,它工作正常。但是当我更新所有行时:
UPDATE cad_bilhetes
SET ligacao_acobrar = 'False'
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
消息 512,级别 16,状态 1,过程 TG_CAD_BILHETES_UPDATE,第 34 行子查询返回了 1 个以上的值。当子查询跟随 =、!=、<、<=、>、>= 或当子查询用作表达式时,这是不允许的。该语句已终止。
在 TG_CAD_BILHETES_UPDATE 的第 34 行中有:
DECLARE @VALOR_LIGACOES_DDI_ATUAL DECIMAL(7,2)
Run Code Online (Sandbox Code Playgroud)
触发器的开始:
ALTER TRIGGER [dbo].[TG_CAD_BILHETES_UPDATE]
ON [dbo].[CAD_BILHETES]
INSTEAD OF UPDATE
AS
BEGIN
DECLARE @ID INT
DECLARE @VALOR_BILHETE_NOVO DECIMAL(7,2)
DECLARE @VALOR_BILHETE_ATUAL DECIMAL(7,2)
DECLARE @ENCONTROU INT
DECLARE @ID_CONTRATACAO INT
DECLARE @TIPO VARCHAR(2)
DECLARE @TIPO_APARELHO VARCHAR(1)
DECLARE @ID_COMPETENCIA INT
DECLARE @ID_CONTRATACAO_ATUAL INT
DECLARE @ID_CONTRATACAO_NOVO INT
DECLARE @VALOR_LIGACOES_DDD_FIXO_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_DDD_MOVEL_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_LOCAL_MOVEL_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_LOCAL_FIXO_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_DDI_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_VOIP_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_TOM_REMOTO_NOVO DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_DDD_FIXO_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_DDD_MOVEL_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_LOCAL_MOVEL_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_LOCAL_FIXO_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_DDI_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_VOIP_ATUAL DECIMAL(7,2)
DECLARE @VALOR_LIGACOES_TOM_REMOTO_ATUAL DECIMAL(7,2)
DECLARE @VALOR_OS_NOVO DECIMAL(7,2)
DECLARE @FOI_CANCELADO_NOVO BIT
SET @ENCONTROU = 0
SET @ID = (SELECT ID FROM INSERTED)
SET @ID_COMPETENCIA = (SELECT ID_COMPETENCIA FROM INSERTED)
SET @VALOR_LIGACOES_DDD_FIXO_NOVO = 0
SET @VALOR_LIGACOES_DDD_MOVEL_NOVO = 0
SET @VALOR_LIGACOES_LOCAL_MOVEL_NOVO = 0
SET @VALOR_LIGACOES_LOCAL_FIXO_NOVO = 0
SET @VALOR_LIGACOES_DDI_NOVO = 0
SET @VALOR_LIGACOES_VOIP_NOVO = 0
SET @VALOR_LIGACOES_TOM_REMOTO_NOVO = 0
SET @VALOR_LIGACOES_DDD_FIXO_ATUAL = 0
SET @VALOR_LIGACOES_DDD_MOVEL_ATUAL = 0
SET @VALOR_LIGACOES_LOCAL_MOVEL_ATUAL = 0
SET @VALOR_LIGACOES_LOCAL_FIXO_ATUAL = 0
SET @VALOR_LIGACOES_DDI_ATUAL = 0
SET @VALOR_LIGACOES_VOIP_ATUAL = 0
SET @VALOR_LIGACOES_TOM_REMOTO_ATUAL = 0
SELECT TOP (1)
@TIPO = SUBSTRING(B.TIPO, 2, 2), @TIPO_APARELHO = SUBSTRING(B.TIPO, 4, 1),
@VALOR_BILHETE_ATUAL = B.VALOR,
@ID_CONTRATACAO_ATUAL = C.ID
FROM CAD_BILHETES AS B
JOIN CAD_CONTRATACAO AS C
ON B.ID_PRODUTO = C.ID_PRODUTO AND (B.DATA_HORA >= C.DATA_INICIO AND (C.DATA_FIM IS NULL OR B.DATA_HORA <= C.DATA_FIM))
WHERE B.ID = @ID and
C.FOI_CANCELADA= 'FALSE'
IF @ID_CONTRATACAO_ATUAL IS NOT NULL
BEGIN
IF(@TIPO = 'IV')
BEGIN
SET @VALOR_LIGACOES_VOIP_ATUAL = @VALOR_BILHETE_ATUAL
END
ELSE
IF(@TIPO = 'IT')
BEGIN
SET @VALOR_LIGACOES_TOM_REMOTO_ATUAL = @VALOR_BILHETE_ATUAL
END
ELSE
IF(@TIPO = 'EL')
BEGIN
IF(@TIPO_APARELHO = 'F')
BEGIN
SET @VALOR_LIGACOES_LOCAL_FIXO_ATUAL = @VALOR_BILHETE_ATUAL
END
ELSE
IF(@TIPO_APARELHO = 'M')
BEGIN
SET @VALOR_LIGACOES_LOCAL_MOVEL_ATUAL = @VALOR_BILHETE_ATUAL
END
END
ELSE
IF(@TIPO = 'EN')
BEGIN
IF(@TIPO_APARELHO = 'F')
BEGIN
SET @VALOR_LIGACOES_DDD_FIXO_ATUAL = @VALOR_BILHETE_ATUAL
END
ELSE
IF(@TIPO_APARELHO = 'M')
BEGIN
SET @VALOR_LIGACOES_DDD_MOVEL_ATUAL = @VALOR_BILHETE_ATUAL
END
END
ELSE
IF(@TIPO = 'EI')
BEGIN
SET @VALOR_LIGACOES_DDI_ATUAL = @VALOR_BILHETE_ATUAL
END
END
SELECT @TIPO = SUBSTRING(I.TIPO, 2, 2), @TIPO_APARELHO = SUBSTRING(I.TIPO, 4, 1),
@VALOR_BILHETE_NOVO = I.VALOR,
@ID_CONTRATACAO_NOVO = C.ID,
@FOI_CANCELADO_NOVO = I.FOI_CANCELADO,
@ID_COMPETENCIA = I.ID_COMPETENCIA
FROM INSERTED AS I
JOIN CAD_CONTRATACAO AS C
ON I.ID_PRODUTO = C.ID_PRODUTO AND (I.DATA_HORA >= C.DATA_INICIO AND (I.DATA_HORA <= C.DATA_FIM OR C.DATA_FIM IS NULL))
WHERE C.FOI_CANCELADA= 'FALSE'
IF @ID_CONTRATACAO_NOVO IS NOT NULL
BEGIN
IF(@TIPO = 'IV')
BEGIN
SET @VALOR_LIGACOES_VOIP_NOVO = @VALOR_BILHETE_NOVO
END
ELSE
IF(@TIPO = 'IT')
BEGIN
SET @VALOR_LIGACOES_TOM_REMOTO_NOVO = @VALOR_BILHETE_NOVO
END
ELSE
IF(@TIPO = 'EL')
BEGIN
IF(@TIPO_APARELHO = 'F')
BEGIN
SET @VALOR_LIGACOES_LOCAL_FIXO_NOVO = @VALOR_BILHETE_NOVO
END
ELSE
IF(@TIPO_APARELHO = 'M')
BEGIN
SET @VALOR_LIGACOES_LOCAL_MOVEL_NOVO = @VALOR_BILHETE_NOVO
END
END
ELSE
IF(@TIPO = 'EN')
BEGIN
IF(@TIPO_APARELHO = 'F')
BEGIN
SET @VALOR_LIGACOES_DDD_FIXO_NOVO = @VALOR_BILHETE_NOVO
END
ELSE
IF(@TIPO_APARELHO = 'M')
BEGIN
SET @VALOR_LIGACOES_DDD_MOVEL_NOVO = @VALOR_BILHETE_NOVO
END
END
ELSE
IF(@TIPO = 'EI')
BEGIN
SET @VALOR_LIGACOES_DDI_NOVO = @VALOR_BILHETE_NOVO
END
SELECT @ENCONTROU = 1
FROM CAD_CUSTO_PRODUTO
WHERE ID_CONTRATACAO = @ID_CONTRATACAO_NOVO AND
ID_COMPETENCIA=@ID_COMPETENCIA
IF(@ENCONTROU = 0)
BEGIN
INSERT INTO CAD_CUSTO_PRODUTO
VALUES (@ID_CONTRATACAO_NOVO, @ID_COMPETENCIA, NULL, 0, 0, 0, @VALOR_LIGACOES_DDD_FIXO_NOVO,
@VALOR_LIGACOES_DDD_MOVEL_NOVO, @VALOR_LIGACOES_LOCAL_MOVEL_NOVO, @VALOR_LIGACOES_LOCAL_FIXO_NOVO,
@VALOR_LIGACOES_DDI_NOVO, @VALOR_LIGACOES_VOIP_NOVO, @VALOR_LIGACOES_TOM_REMOTO_NOVO)
END
ELSE
BEGIN
IF (@FOI_CANCELADO_NOVO = 1)
BEGIN
UPDATE CAD_CUSTO_PRODUTO
SET VALOR_LIGACOES_DDD_FIXO = VALOR_LIGACOES_DDD_FIXO - @VALOR_LIGACOES_DDD_FIXO_ATUAL,
VALOR_LIGACOES_DDD_MOVEL = VALOR_LIGACOES_DDD_MOVEL - @VALOR_LIGACOES_DDD_MOVEL_ATUAL,
VALOR_LIGACOES_LOCAL_MOVEL = VALOR_LIGACOES_LOCAL_MOVEL - @VALOR_LIGACOES_LOCAL_MOVEL_ATUAL,
VALOR_LIGACOES_LOCAL_FIXO = VALOR_LIGACOES_LOCAL_FIXO - @VALOR_LIGACOES_LOCAL_FIXO_ATUAL,
VALOR_LIGACOES_DDI = VALOR_LIGACOES_DDI - @VALOR_LIGACOES_DDI_ATUAL,
VALOR_LIGACOES_VOIP = VALOR_LIGACOES_VOIP - @VALOR_LIGACOES_VOIP_ATUAL,
VALOR_LIGACOES_TOM_REMOTO = VALOR_LIGACOES_TOM_REMOTO - @VALOR_LIGACOES_TOM_REMOTO_ATUAL
WHERE ID_CONTRATACAO = @ID_CONTRATACAO_ATUAL AND ID_COMPETENCIA = @ID_COMPETENCIA
END
ELSE
BEGIN
UPDATE CAD_CUSTO_PRODUTO
SET VALOR_LIGACOES_DDD_FIXO = VALOR_LIGACOES_DDD_FIXO + (@VALOR_LIGACOES_DDD_FIXO_NOVO - @VALOR_LIGACOES_DDD_FIXO_ATUAL),
VALOR_LIGACOES_DDD_MOVEL = VALOR_LIGACOES_DDD_MOVEL + (@VALOR_LIGACOES_DDD_MOVEL_NOVO - @VALOR_LIGACOES_DDD_MOVEL_ATUAL),
VALOR_LIGACOES_LOCAL_MOVEL = VALOR_LIGACOES_LOCAL_MOVEL + (@VALOR_LIGACOES_LOCAL_MOVEL_NOVO - @VALOR_LIGACOES_LOCAL_MOVEL_ATUAL),
VALOR_LIGACOES_LOCAL_FIXO = VALOR_LIGACOES_LOCAL_FIXO + (@VALOR_LIGACOES_LOCAL_FIXO_NOVO - @VALOR_LIGACOES_LOCAL_FIXO_ATUAL),
VALOR_LIGACOES_DDI = VALOR_LIGACOES_DDI + (@VALOR_LIGACOES_DDI_NOVO - @VALOR_LIGACOES_DDI_ATUAL),
VALOR_LIGACOES_VOIP = VALOR_LIGACOES_VOIP + (@VALOR_LIGACOES_VOIP_NOVO - @VALOR_LIGACOES_VOIP_ATUAL),
VALOR_LIGACOES_TOM_REMOTO = VALOR_LIGACOES_TOM_REMOTO + (@VALOR_LIGACOES_TOM_REMOTO_NOVO - @VALOR_LIGACOES_TOM_REMOTO_ATUAL)
WHERE ID_CONTRATACAO = @ID_CONTRATACAO_ATUAL AND ID_COMPETENCIA = @ID_COMPETENCIA
END
END
END
UPDATE CAD_BILHETES
SET ID_PREFIXO = I.ID_PREFIXO,
ID_PRODUTO = I.ID_PRODUTO,
ID_COMPETENCIA = I.ID_COMPETENCIA,
DATA_HORA = I.DATA_HORA,
DURACAO = I.DURACAO,
TIPO = I.TIPO,
NUMERO_EXTERNO = I.NUMERO_EXTERNO,
RAMAL = I.RAMAL,
SENHA_AUTORIZACAO = I.SENHA_AUTORIZACAO,
CODIGO_DEPENDENCIA = I.CODIGO_DEPENDENCIA,
CRITICA = I.CRITICA,
[STATUS] = I.STATUS,
VALOR = I.VALOR,
SEQUENCIAL = I.SEQUENCIAL,
FOI_TARIFADO = I.FOI_TARIFADO,
FOI_CANCELADO = I.FOI_CANCELADO,
DURACAO_TARIFACAO = I.DURACAO_TARIFACAO
FROM INSERTED AS I
WHERE CAD_BILHETES.ID = I.ID
END
Run Code Online (Sandbox Code Playgroud)
SET @ID = (SELECT ID FROM INSERTED)
SET @ID_COMPETENCIA = (SELECT ID_COMPETENCIA FROM INSERTED)
这是一个常见的误解,即每行受影响触发一次,而实际上每个 DML 语句只触发一次触发器主体**。
在触发器主体中,表inserted
和deleted
表包含受操作影响的所有行。这样做是出于(至少)两个原因:
单行触发器代码可能会在很长一段时间内不被注意,因为它可能合法地适用于您的用例,并且只有在有人决定影响多于一行时才会中断。更糟糕的是,触发代码实际上可能会成功,并最终做错事而没有错误。
不幸的是,在编写触发器时没有安全措施可以告诉您此信息,因此您很幸运地发现了此错误!
**对于百姓心中与SQL Server 2008+读这篇文章,MERGE
分别触发了3种不同的类型,因为它实际上只是一个事务“宏”干什么INSERT
+ UPDATE
+DELETE
在相同的T-SQL语句。