2016-06-07 61 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做的所有事情。 所以是的,我可以在這裏設置一個約束。我應該把兩個,一個用於實際數量,另一個用於總量。你如何告訴約束來限制另一個字段的值取決於它自己的值? (這有點令人困惑)。 謝謝, –