2016-06-07 82 views
0

早安人,触发与identation光标[编辑]

这是我的第一篇文章在这里,我已经工作了一个数据库的APP我的工作,我需要在触发我一些线索这让我很生气。

编辑:

鉴于未来结构:

用户表:

[dbo].[ENGIE_Users] 
(
[dbID] [int] IDENTITY(1,1) NOT NULL, 
[Nombre] [nvarchar](100) NOT NULL, 
[Apellidos] [nvarchar](200) NOT NULL, 
[HashContraseña] [binary](64) NOT NULL, 
[Email] [nvarchar](150) NOT NULL, 
[Direccion] [nvarchar](150) NOT NULL, 
[Codigo Postal] [nvarchar](5) NOT NULL, 
[Telefono] [nvarchar](12) NOT NULL, 
[Venta a Nº Cliente] [nvarchar](10) NOT NULL, 
[POS Asignado] [nvarchar](10) NOT NULL, 
[User_Number] AS ([dbo].[EngieUsers]([dbID])), 
[Salt] [uniqueidentifier] NULL 

约束: DBID主键 电子邮件无PK独特

这就是我们存放来自APP的用户。

用户材质表:

[dbo].[ENGIE_User_Material] 
(
[ID User] [int] NOT NULL, 
[EAN] [nvarchar](13) NOT NULL, 
[Product Number] [nvarchar](20) NOT NULL, 
[Venta] [tinyint] NOT NULL, 
[Cantidad Actual] [int] NOT NULL, 
[Cantidad Total] [int] NOT NULL, 
[Descripcion Corta] [nvarchar](100) NOT NULL, 
[PVP Neto] [decimal](38, 20) NOT NULL, 
[% DTO] [decimal](38, 20) NOT NULL, 

主键ID用户+产品型号+ EAN ID用户从用户引用DBID。

此表用于存储每个用户已经对其“帐户”进行分配的产品数量。

Orders表:

[dbo].[ENGIE_Ended_Orders] 
(
[dbID] [int] IDENTITY(1,1) NOT NULL, 
[ID User] [int] NOT NULL, 
[Procesado] [tinyint] NOT NULL, 
[Finalizado] [tinyint] NOT NULL, 
[Fecha de realizacion] [date] NOT NULL, 
[OT] [nvarchar](20) NOT NULL, 
[Order Id] AS ([dbo].[EngiePedidos]([dbID])), 
[Total Pedido] [decimal](38, 20) NULL, 

主键DBID

ID用户外键DBID从用户 引用此表将包含订单的 “头”。

订单内容表

[dbo].[ENGIE_Order_Content]  
(
[Order Id] [int] NOT NULL, 
[Product Number] [nchar](20) NOT NULL, 
[Procesado] [tinyint] NOT NULL, 
[Finalizado] [tinyint] NOT NULL, 
[Fecha de realizacion] [date] NOT NULL, 
[Cantidad] [int] NOT NULL, 
[ID Pedido] [nchar](8) NULL, 

主键产品编号+订单标识 外键订单标识引用订单DBID

因此,鉴于这种结构我需要的是下一个限制:

On User-Material: 它自己的实际数量永远不必克服总数量。 (插入/更新)

订单 - 内容: 当订单被插入或更新时,它必须满足上述限制(所以如果你问5,你必须有5个单位可供你购买此产品) 此外,当它被插入/更新/删除时,触发器必须计算“订单总额”,方程式是(数量*(价格 - (价格* 100 /折扣)))。

在订单: 所以还有两个表(与订单/订单内容相同的结构,称为终止订单/终止订单的范围)witch此表将传递这些表的所有行到其他2当布尔值[Finalizado] = 1,并且将恢复这些项目用户所关联的实际数量,这些项目位于此结束订单中。

工作完成:

触发器: 在用户材料

ALTER TRIGGER [dbo].[Qty_Restriction] 
ON [ENGIE].[dbo].[ENGIE_User_Material] 
INSTEAD OF INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 
    IF(SELECT [Cantidad Actual] FROM INSERTED) > (SELECT [Cantidad Total] FROM INSERTED) 
    BEGIN 
     RAISERROR('La Cantidad Actual no debe superar la Cantidad Total',18,1); 
    END 
    ELSE BEGIN 
     INSERT INTO ENGIE.dbo.ENGIE_User_Material SELECT [ID User],[EAN], [Product Number],[Venta],[Cantidad Actual],[Cantidad Total],[Descripcion Corta], [PVP Neto],[% DTO] FROM INSERTED; 
    END 
END 

这会不会让你插入比总量更实际数量的REG。

ALTER TRIGGER [dbo].[Qty_Restriction_2] 

ON [ENGIE].[dbo].[ENGIE_User_Material] 

INSTEAD OF UPDATE 

AS 

DECLARE @material varchar(13) 
DECLARE @pno varchar(20) 
DECLARE @usuario int 

SET @material = (SELECT [EAN] FROM INSERTED) 
SET @pno = (SELECT [Product Number] FROM INSERTED) 
SET @usuario = (SELECT [ID User] FROM INSERTED) 

BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE([Cantidad Actual]) 
    BEGIN 
     IF(SELECT [Cantidad Actual] FROM INSERTED) > (SELECT [Cantidad Total] FROM INSERTED) 
     BEGIN 
      RAISERROR('La Cantidad Actual no debe superar la Cantidad Total',18,1); 
     END 
     ELSE BEGIN 
      UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [Cantidad Actual] = (SELECT [Cantidad Actual] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
     END 
    END 
    IF UPDATE([Cantidad Total]) 
    BEGIN 
     IF(SELECT [Cantidad Actual] FROM INSERTED) > (SELECT [Cantidad Total] FROM INSERTED) 
     BEGIN 
      RAISERROR('La Cantidad Actual no debe superar la Cantidad Total',18,1); 
     END 
     ELSE BEGIN 
      UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [Cantidad Total] = (SELECT [Cantidad Total] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
     END 
    END 
    IF UPDATE([Venta]) 
    BEGIN 
     UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [Venta] = (SELECT [Venta] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
    END 
    IF UPDATE([Descripcion Corta]) 
    BEGIN 
     UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [Descripcion Corta] = (SELECT [Descripcion Corta] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
    END 
    IF UPDATE([PVP Neto]) 
    BEGIN 
     UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [PVP Neto] = (SELECT [PVP Neto] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
    END 
    IF UPDATE([% DTO]) 
    BEGIN 
     UPDATE [ENGIE].[dbo].[ENGIE_User_Material] SET [% DTO] = (SELECT [% DTO] FROM INSERTED) WHERE [Product Number] = @pno AND [EAN] = @material AND [ID User] = @usuario 
    END 
END 

这是一样的,但与更新。

订单:

CREATE TRIGGER [dbo].[TransferenceOrders_Inner] 

    ON [ENGIE].[dbo].[ENGIE_Orders] 

    AFTER UPDATE 

AS 

DECLARE @material nvarchar(20) 
DECLARE @cant int 
DECLARE @cantant int 
DECLARE @usr int 

DECLARE CURSOR_CANTIDAD CURSOR FOR 
SELECT [Cantidad],[Product Number],[ID User] FROM [ENGIE].[dbo].[ENGIE_Order_Content] A, INSERTED I WHERE A.[Numero_Pedido] = I.Numero_Pedido 

BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE([Finalizado]) 
    BEGIN 
     UPDATE A SET [Finalizado] = I.Finalizado FROM [ENGIE].[dbo].[ENGIE_Orders] A INNER JOIN INSERTED I ON A.dbID = I.dbID; 

     INSERT INTO [ENGIE].dbo.[ENGIE_Ended_Orders] ([Numero_Pedido],[ID User],[Fecha de realizacion],[OT],[ID Pedido],[Total Pedido]) 
    (SELECT [dbID],[ID User],[Fecha de realizacion],[OT],[Numero_Pedido],[Total Pedido] FROM INSERTED) 

     INSERT INTO [ENGIE].dbo.[ENGIE_Ended_Order_Content] ([Numero_Pedido],[Product Number],[Fecha de realizacion],[Cantidad],[ID Pedido]) 
    (SELECT [Numero_Pedido],[Product Number],[Fecha de realizacion],[Cantidad],[ID Pedido] FROM [ENGIE].[dbo].[ENGIE_Order_Content] A INNER JOIN INSERTED I ON A.Numero_Pedido = I.dbID) 

     OPEN CURSOR_CANTIDAD 
     FETCH CURSOR_CANTIDAD INTO @cant,@material,@usr 
     WHILE (@@FETCH_STATUS = 0) 
     BEGIN 
      UPDATE ENGIE.dbo.ENGIE_User_Material SET [Cantidad Actual] = (SELECT [Cantidad Actual] FROM ENGIE.dbo.ENGIE_User_Material A,INSERTED I WHERE A.[Product Number] = (SELECT [Product Number] FROM ENGIE.dbo.[ENGIE_Order_Content] B,INSERTED C WHERE B.Numero_Pedido = C.dbID) 
     AND A.[ID User] = I.[ID User])[email protected] WHERE [Product Number] = @material AND [ID User] = @usr)   
      FETCH CURSOR_CANTIDAD INTO @cant,@material,@usr 
     END 
     CLOSE CURSOR_CANTIDAD; 
     DELETE A FROM [ENGIE].[dbo].[ENGIE_Orders] A INNER JOIN INSERTED I ON I.[dbID] = A.[dbID] AND A.[ID User] = I.[ID User]; 
    END 
    DEALLOCATE CURSOR_CANTIDAD; 
END 

这触发需要游标,因为它有补充,它只是处理顺序的内容的数量。

在Order_Content:

ALTER TRIGGER [dbo].[AutoIDOrder_DEL] 

ON [ENGIE].[dbo].[ENGIE_Order_Content] 

AFTER DELETE 

AS 

DECLARE @numped int 
DECLARE @prod nchar(20) 
DECLARE @pvp decimal(38,20) 
DECLARE @pvpsdto decimal(38,20) 
DECLARE @dto decimal(38,20) 
DECLARE @cantidad int 

SET @numped = (SELECT Numero_Pedido FROM INSERTED) 
SET @prod = (SELECT [Product Number] FROM INSERTED) 
SET @cantidad = (SELECT [Cantidad] FROM INSERTED) 
SET @pvp = (SELECT [Total Pedido] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] = @numped) 

BEGIN 
    SET NOCOUNT ON; 
    SET @pvpsdto = (SELECT [PVP Neto] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = @prod) 
    SET @dto = (SELECT [% DTO] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = @prod) 
    UPDATE [ENGIE].[dbo].[ENGIE_Orders] SET [Total Pedido] = @pvp-(@cantidad*((@pvpsdto*100)/@dto)) WHERE [dbID] = @numped 
END 

,当你从订单内容删除注册表这一次将更新从订单“订单总计”。

ALTER TRIGGER [dbo].[Qty_Restriction_3] 

ON [ENGIE].[dbo].[ENGIE_Order_Content] 

INSTEAD OF INSERT 

AS 

DECLARE @cantAnt int 
DECLARE @cantAct int 
DECLARE @cant int 
DECLARE @pvpsdto decimal(38,20) 
DECLARE @dto decimal(38,20) 
DECLARE @total decimal(38,20) 

SET @cant = (SELECT [Cantidad] FROM INSERTED) 
SET @cantAnt = (SELECT [Cantidad Total] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @cantAct = (SELECT [Cantidad Actual] FROM [ENGIE].[dbo].[ENGIE_User_Material]WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @pvpsdto = (SELECT [PVP Neto] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @dto = (SELECT [% DTO] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @total = (SELECT [Total Pedido] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED)) 
IF(@total IS NULL) 
BEGIN 
    SET @total = 0.0 
END 

BEGIN 
    SET NOCOUNT ON; 
    BEGIN 
     IF((@[email protected]) > @cantAnt) 
     BEGIN 
      RAISERROR('La Cantidad Actual no debe superar la Cantidad Total',18,1); 
     END 
     ELSE BEGIN 
      INSERT INTO ENGIE.dbo.ENGIE_Order_Content SELECT * FROM INSERTED; 
      UPDATE [ENGIE].[dbo].[ENGIE_Order_Content] SET [ID Pedido] = (SELECT [Numero_Pedido] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] LIKE (SELECT [Numero_Pedido] FROM INSERTED)) WHERE [Numero_Pedido] LIKE (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number] LIKE (SELECT [Product Number] FROM INSERTED); 
      UPDATE [ENGIE].[dbo].[ENGIE_Order_Content] SET [Fecha de realizacion] = (SELECT [Fecha de realizacion] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED)) WHERE [Numero_Pedido] LIKE (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number] LIKE (SELECT [Product Number] FROM INSERTED); 
     ----> AUQUI CALCULO DE TOTAL 

      UPDATE [ENGIE].[dbo].[ENGIE_Orders] SET [Total Pedido] = (@total+(@cant*(@pvpsdto-((@pvpsdto*@dto)/100)))) WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED) 
     END 
    END 
END 

这一次将避免插入订单内容的数量不符合(实际数量< =总量)的要求+将计算总的秩序的基础,要添加的productss到订单。

ALTER TRIGGER [dbo].[Qty_Restriction_4] 

ON [ENGIE].[dbo].[ENGIE_Order_Content] 

INSTEAD OF UPDATE 

AS 

DECLARE @cantAnt int 
DECLARE @cantAct int 
DECLARE @cant int 
DECLARE @pvpsdto decimal(38,20) 
DECLARE @dto decimal(38,20) 
DECLARE @bool bit 
DECLARE @total decimal(38,20) 

SET @bool = 0; 
SET @cant = (SELECT [Cantidad] FROM INSERTED) 
SET @userId = (SELECT [ID User] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED)) 
SET @cantAnt = (SELECT [Cantidad Total] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [ID User] = @userId AND [Product Number] = (SELECT [Product Number] FROM INSERTED)) 
SET @cantAct = (SELECT [Cantidad Actual] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [ID User] = @userId AND [Product Number] = (SELECT [Product Number] FROM INSERTED)) 
SET @pvpsdto = (SELECT [PVP Neto] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @dto = (SELECT [% DTO] FROM [ENGIE].[dbo].[ENGIE_User_Material] WHERE [Product Number] = (SELECT [Product Number] FROM INSERTED) AND [ID User] = (SELECT [ID User] FROM INSERTED)) 
SET @total = (SELECT [Total Pedido] FROM [ENGIE].[dbo].[ENGIE_Orders] WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED)) 
IF(@total IS NULL) 
BEGIN 
    SET @total = 0.0 
END 

BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE([Cantidad]) 
    BEGIN 
     IF((@[email protected]) > @cantAnt) 
     BEGIN 
      RAISERROR('La Cantidad Actual no debe superar la Cantidad Total',18,1); 
     --->ROLLBACK TRANSACTION; 
     END 
     ELSE BEGIN 
      UPDATE ENGIE.dbo.ENGIE_Order_Content SET [Cantidad] = (SELECT [Cantidad] FROM inserted) WHERE [Numero_Pedido]= (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number]= (SELECT [Product Number] FROM INSERTED) 
      SET @bool = 1; 
     END; 
    END; 
    IF UPDATE([Procesado]) 
    BEGIN 
     UPDATE ENGIE.dbo.ENGIE_Order_Content SET [Procesado] = (SELECT [Procesado] FROM inserted) WHERE [Numero_Pedido]= (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number]= (SELECT [Product Number] FROM INSERTED) 
    END; 
    IF UPDATE([Finalizado]) 
    BEGIN 
     UPDATE ENGIE.dbo.ENGIE_Order_Content SET [Finalizado] = (SELECT [Finalizado] FROM inserted) WHERE [Numero_Pedido]= (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number]= (SELECT [Product Number] FROM INSERTED) 
    END; 
    IF UPDATE([ID Pedido]) 
    BEGIN 
     UPDATE ENGIE.dbo.ENGIE_Order_Content SET [ID Pedido] = (SELECT [ID Pedido] FROM inserted) WHERE [Numero_Pedido]= (SELECT [Numero_Pedido] FROM INSERTED) AND [Product Number]= (SELECT [Product Number] FROM INSERTED) 
    END; 
---> AQUI METER LO DEL AFTER UPDATE, PARA QUE NO HAYA PROBLEMA, CON UN BOOLEAN 
    IF (@bool = 1) 
    BEGIN 
    SET NOCOUNT ON; 
     UPDATE [ENGIE].[dbo].[ENGIE_Orders] SET [Total Pedido] = (@total+(@cant*(@pvpsdto-((@pvpsdto*@dto)/100)))) WHERE [dbID] = (SELECT [Numero_Pedido] FROM INSERTED) 
    END; 
END 

这最后一个假装做同样的插入,但在更新,使得实际数量的限制,工作,到[订单总计]列

+0

写一个存储过程 –

+0

你正在使用'sql-server'或'plsql'吗?请删除不相关的标签。 –

+0

完成,它的tsql没有plsql。 –

回答

1

你触发不处理给值多行插入。如果

SET @usuario = (SELECT [ID User] FROM INSERTED) 

返回多个值。它会失败。触发器内的光标是非常糟糕的事情。您应该重新使用基于集合的方式写你的触发 你的第一个4个报表应重新写入

UPDATE A 
SET [Finalizado] = i.Finalizado 
FROM [ENGIE].[dbo].[ENGIE_Orders] A 
INNER JOIN INSERTED I ON a.dbID = i.dbid; 

INSERT INTO [ENGIE].dbo.[ENGIE_Ended_Orders] (
    [Numero_Pedido] 
    ,[ID User] 
    ,[Fecha de realizacion] 
    ,[OT] 
    ,[ID Pedido] 
    ) 
SELECT [dbID] 
    ,[ID User] 
    ,[Fecha de realizacion] 
    ,[OT] 
    ,[Numero_Pedido] 
FROM [ENGIE].[dbo].[ENGIE_Orders] 
FROM inserted 

INSERT INTO [ENGIE].dbo.[ENGIE_Ended_Order_Content] (
    [Numero_Pedido] 
    ,[Product Number] 
    ,[Fecha de realizacion] 
    ,[Cantidad] 
    ,[ID Pedido] 
    ) 
SELECT [Numero_Pedido] 
    ,[Product Number] 
    ,[Fecha de realizacion] 
    ,[Cantidad] 
    ,[ID Pedido] 
FROM [ENGIE].[dbo].[ENGIE_Order_Content] A 
INNER JOIN INSERTED I ON A.Numero_Pedido = I.Dbid 

DELETE A 
FROM [ENGIE].[dbo].[ENGIE_Orders] A 
INNER JOIN INSERTED I ON 
WHERE I.[dbID] = A.DBID 
    AND A.[ID User] = I.USERID; 

我不知道我见过你的标准(especillay的加入,请做一次检查就可以了),但触发应用基于集合的逻辑重写,我希望光标也可以被删除

+0

早上,如果我想在自己的表中触发一个触发器,这将不会让更新实际数量,除非它低于或等于总量,那么我将如何使用aritmetic操作?无法使用: INSTEAD OF UPDATE ... AS .... ... IF SELECT [Cantidad实际]为由插入> SELECT [Cantidad总计]从安装, BEGIN --->引发错误 END ELSE BEGIN - > PERFORM UPDATE END 我怎么能绕过这个问题呢? –

+0

@BorisPomarol,你可以在列上添加一个约束吗? –

+0

在Dynamics NAV中将C/AL工作转换为纯T-SQL的过渡使我在某些方面受到了影响,其核心是我不能理解我能用T-SQL做的所有事情。 所以是的,我可以在这里设置一个约束。我应该把两个,一个用于实际数量,另一个用于总量。你如何告诉约束来限制另一个字段的值取决于它自己的值? (这有点令人困惑)。 谢谢, –