这两天VMI的项目出了很多小问题,主要是sourcing部门对已经注册VMI的料进行大批量的删除和价格更新,这让原本存在的VMI订单来不及取消,或者VMI发票上的单价与实际系统中的单价产生了一定的差异。于是先通过trigger来控制,开始用c#以来很久没碰trigger了,创建之前先学习一下;

基于需求,这里测试主要是基于DML操作,另外要求在游标中使用cursor来达到批量操作的目的,另外需要对insert/delete/update分别测试,以适应需求;

<从codeproject找了一个简单的例子>

 

   
   
   
   
  1. CREATE TABLE Employee_Test 
  2. Emp_ID INT Identity, 
  3. Emp_name Varchar(100), 
  4. Emp_Sal Decimal (10,2) 
  5.  
  6. INSERT INTO Employee_Test VALUES ('Anees',1000); 
  7. INSERT INTO Employee_Test VALUES ('Rick',1200); 
  8. INSERT INTO Employee_Test VALUES ('John',1100); 
  9. INSERT INTO Employee_Test VALUES ('Stephen',1300); 
  10. INSERT INTO Employee_Test VALUES ('Maria',1400); 
  11.  
  1. CREATE TABLE Employee_Test_Audit 
  2. Emp_ID int
  3. Emp_name varchar(100), 
  4. Emp_Sal decimal (10,2), 
  5. Audit_Action varchar(100), 
  6. Audit_Timestamp datetime 

1). Insert , 支持批量,

 

   
   
   
   
  1. ALTER TRIGGER tradertest ON Employee_Test 
  2. FOR INSERT  
  3. as  
  4.    DECLARE @empsal INT,@empname VARCHAR(100) 
  5.    DECLARE @cur_1 CURSOR 
  6.    SET @cur_1 = CURSOR FOR 
  7.        SELECT Emp_Sal,Emp_name FROM inserted 
  8.    OPEN @cur_1 
  9.    FETCH NEXT FROM @cur_1 INTO @empsal,@empname 
  10.    WHILE @@FETCH_STATUS=0 
  11.    BEGIN 
  12.       INSERT INTO Employee_Test_Audit (Emp_Sal,Emp_name) VALUES (@empsal,@empname) 
  13.       FETCH NEXT FROM @cur_1 INTO @empsal,@empname 
  14.    END 
  15.    CLOSE @cur_1 
  16.    DEALLOCATE @cur_1 
  17. GO  
  18. INSERT INTO Employee_Test (Emp_name,Emp_Sal) 
  19. SELECT TOP 10 Emp_name,Emp_Sal FROM Employee_Test 
  20. GO 
  21. SELECT * FROM  Employee_Test_Audit 

2)  Delete 操作,在里面进行判断,如果是删除John的薪水,需要保留到audit表中:

 

   
   
   
   
  1. alter TRIGGER traderDel ON Employee_Test 
  2. FOR DELETE 
  3. as 
  4.   DECLARE @empsal FLOAT,@empname VARCHAR(100) 
  5.   DECLARE @cur_1 CURSOR 
  6.   SET @cur_1 = CURSOR FOR 
  7.       SELECT Emp_Sal,Emp_name FROM DELETED 
  8.   OPEN @cur_1 
  9.   FETCH NEXT FROM @cur_1 INTO @empsal,@empname 
  10.   WHILE @@FETCH_STATUS=0 
  11.   BEGIN 
  12.       --- 循环里面加以判断,如果是John则禁止删除 
  13.       IF @empname='John' 
  14.          INSERT INTO Employee_Test_Audit (Emp_Sal,Emp_name,Audit_Action) VALUES  
  15.          (@empsal,@empname,'Delete John Sal'
  16.       FETCH NEXT FROM @cur_1 INTO @empsal,@empname    
  17.   END 
  18.    CLOSE @cur_1 
  19.    DEALLOCATE @cur_1 
  20. GO 
  21. DELETE Employee_Test WHERE Emp_Sal=1100 
  22. GO 
  23. SELECT * FROM Employee_Test_Audit WHERE Audit_Action LIKE 'Delet%' 
  24.     

 

3) Update, 要求把对修改薪水的操作记录下来:

 

   
   
   
   
  1. ALTER TRIGGER traderUpd ON Employee_Test 
  2. FOR UPDATE 
  3. as 
  4.    DECLARE @empsal FLOAT,@empname VARCHAR(100),@i int 
  5.    DECLARE @cur_1 CURSOR 
  6.    SET @i=1 
  7.    SET @cur_1 = CURSOR FOR 
  8.        SELECT Emp_Sal,Emp_name FROM DELETED 
  9.    OPEN @cur_1 
  10.    FETCH NEXT FROM @cur_1 INTO @empsal,@empname 
  11.    WHILE @@FETCH_STATUS=0 
  12.    BEGIN 
  13.        ---此处用Emp_Sal来进行对比,如果相等不操作,否则记录并报错; 
  14.        IF @empsal<>(SELECT MAX(Emp_Sal) FROM INSERTED WHERE Emp_name=@empname)  
  15.        BEGIN 
  16.            INSERT Employee_Test_Audit (Emp_Sal,Emp_name,Audit_Timestamp)  
  17.             VALUES (@empsal,@empname,GETDATE()) 
  18.            RAISERROR(N'Cant udpate his salary!',1,50); 
  19.        END 
  20.        FETCH NEXT FROM @cur_1 INTO @empsal,@empname 
  21.    END 
  22.    CLOSE @cur_1 
  23.    DEALLOCATE @cur_1 
  24.   
  25.  UPDATE Employee_Test SET Emp_sal=1000 WHERE Emp_name='Rick' 
  26.  SELECT * FROM Employee_Test_Audit 
  27.  SELECT * FROM Employee_Test 

总结,Trigger的内容还有很多,以上只是针对DML的简单操作,另外加入了批量功能,帮助自己温习一下trigger.仅供参考。