2011-06-02 76 views
1

我想以下幾點:不能創建觸發器 - SQL Server 2008中

CREATE TRIGGER checkgrade ON 
[Homework4part3].[dbo].[Enrollment] 
FOR INSERT 
AS 
    IF (NEW.grade > 20) 
    BEGIN 
    grade = 3 
    END 

GO 

和我的表如下所示:

招生(當然#,QYear,SUID, 單位,等級)

不知道爲什麼這個錯誤顯示:

Msg 102, Level 15, State 1, Procedure checkgrade, Line 7 
Incorrect syntax near 'grade'. 
+0

你想創建一個檢查約束或觸發器嗎?檢查約束將驗證輸入的值,而觸發器可以做到更多。儘管如此,檢查約束最有可能是進行驗證的最佳位置。 – 2011-06-02 14:48:13

回答

1

有幾個問題。

您需要使用插入的meta表,其中包含新更新/插入的行。 您需要在更新/插入後執行正確的更新,而不是在更新/插入之後執行。

這可能是更接近於真實需要什麼:

CREATE TRIGGER checkgrade ON 
    [Homework4part3].[dbo].[Enrollment] 
    FOR INSERT 
    AS 
    BEGIN 
     SET NOCOUNT ON 

     Update e 
     set grade = 3 
     from 
      [Homework4part3].[dbo].[Enrollment] e 
      join Inserted i on e.SUID = i.SUID and e.[course#] = i.[course#] 
     where i.grade > 20 

    END 

注:這是未經測試,我已經猜到爲你的表的主鍵列。

+0

爲什麼這個錯誤? Msg 2108,Level 15,State 1,Procedure checkgrade,Line 8 由於目標不在當前數據庫中,因此無法在「Homework4part3.dbo.Enrollment」上創建觸發器。 – 2011-06-02 18:07:38

+0

答案出現在消息中:觸發器必須位於數據庫所在的表上。雖然不推薦,但可以從那裏更新外部數據庫中的表格,但應謹慎操作。 – 2011-06-03 08:57:40

3

我將嘗試在各行之間閱讀一下。很明顯,我已經對連接條件做出了最佳猜測。我認爲這是你想要達到的目標。

CREATE TRIGGER checkgrade ON 
[Homework4part3].[dbo].[Enrollment] 
FOR INSERT 
AS 
    UPDATE e 
     SET grade = 3 
     FROM inserted i 
      INNER JOIN enrollment e 
       ON i.coursenum = e.coursenum 
        AND i.QYear = e.QYear 
        AND I.SUID = e.SUID 
     WHERE i.grade > 20 

GO 
-2
IF (SELECT GRADE FROM INSERTED) > 20 
BEGIN 
    UPDATE Enrollment 
    SET GRADE = 3 
    WHERE course = (SELECT COURSE FROM INSERTED), 
    AND QYear = (SELECT QYear FROM INSERTED), 
    AND SUID = (SELECT SUID FROM INSERTED), 
    AND units = (SELECT UNITS FROM INSERTED) 
END 

如果我記得很清楚,你不能在更新語句中使用多個表,從而有望@Joe Stefanelli的回答是行不通的,但這個想法的正確。

希望它有效。

+2

1)儘管您只能更新一個表,但您可以在更新語句中引用多個表,因此我的語法是有效的。 2)你的代碼使得假定'INSERTED'表只包含1行的常見錯誤。 – 2011-06-02 15:08:48

+0

爲什麼會出現此錯誤? Msg 2108,Level 15,State 1,Procedure checkgrade,Line 7 由於目標不在當前數據庫中,因此無法在「Homework4part3.dbo.Enrollment」上創建觸發器。 – 2011-06-02 18:08:34

2

我建議你使用一個而不是觸發器來減少寫入表的次數。在觸發器中使用更新將導致刪除,然後導致插入,因此總共對錶執行三個操作。使用INSTEAD OF觸發器會招致只需一個人操作

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BaseTable]') AND type in (N'U')) 
DROP TABLE [dbo].[BaseTable] 
GO 

CREATE TABLE BaseTable 
    (BaseTableID  int PRIMARY KEY IDENTITY(1,1), 
    [email protected] int, 
    QYear int, 
    SUID int, 
    units int, 
    Grade int 
) 
GO 


--Create an INSTEAD OF INSERT trigger on the table. 
CREATE TRIGGER InsteadTrigger on BaseTable 
INSTEAD OF INSERT 
AS 
BEGIN 

    INSERT INTO BaseTable 
     SELECT 
      [email protected] , 
      QYear , 
      SUID , 
      units , 
      CASE 
      WHEN Grade > 20 THEN 3 
      ELSE Grade 
      END 
     FROM inserted 
END 
GO 

INSERT INTO [deleteme].[dbo].[BaseTable] 
      ([[email protected]] 
      ,[QYear] 
      ,[SUID] 
      ,[units] 
      ,[Grade]) 
    VALUES 
      (10 
      ,10 
      ,10 
      ,10 
      ,10) 
Select * from BaseTable 

INSERT INTO [deleteme].[dbo].[BaseTable] 
      ([[email protected]] 
      ,[QYear] 
      ,[SUID] 
      ,[units] 
      ,[Grade]) 
    VALUES 
      (20 
      ,20 
      ,20 
      ,20 
      ,20) 

Select * from BaseTable 
INSERT INTO [deleteme].[dbo].[BaseTable] 
      ([[email protected]] 
      ,[QYear] 
      ,[SUID] 
      ,[units] 
      ,[Grade]) 
    VALUES 
      (30 
      ,30 
      ,30 
      ,30 
      ,30), 
      (40 
      ,40 
      ,40 
      ,40 
      ,40), 
      (50 
      ,50 
      ,50 
      ,50 
      ,50) 



Select * from BaseTable 


BaseTableID [email protected] QYear SUID units Grade 
1 10 10 10 10 10 
2 20 20 20 20 20 
3 30 30 30 30 3 
4 40 40 40 40 3 
5 50 50 50 50 3 
1

消息102,級別15,狀態1,過程 checkgrade,7號線有語法錯誤 附近 '品位'。

這意味着它們使用的語法是無效的語法。這就是爲什麼其他人給你不同的語法來嘗試。

消息2108,級別15,狀態1,過程 checkgrade,7號線無法創建於 'Homework4part3.dbo.Enrollment' 作爲 目標 觸發不在當前數據庫

這意味着您正試圖在不存在的表上創建觸發器。或者這意味着什麼在這個鏈接: http://social.msdn.microsoft.com/Forums/en/transactsql/thread/64637d9e-8080-411e-a9c6-e228c6437f30

現在讓我們來談談一些觸發器的基礎知識。Firast,最重要的是你必須設計SQL Server中的所有觸發器來處理多行插入,更新或刪除操作。這意味着您必須假定在該操作中更改了多條記錄。

下一個觸發器有兩個可用的僞表,稱爲插入和刪除,它們顯示動作(刪除的表)和動作(插入的表)後的值。兩個表中的更新都有信息,而插入僅在插入和刪除中具有信息,而只刪除信息。您可以使用這些表格查找要執行某些操作的記錄。 @Joe Stefanelli有一個如何使用插入表的好例子。

要理解觸發器的下一件事是他們增加時間到表上的任何操作,因此它們必須儘可能快。因此,不應該使用相關的子查詢,不使用遊標或循環。