触发,排除一些单词

时间:2019-09-19 08:26:10

标签: sql sql-server tsql database-trigger

我有一个与T-SQL中的数据库触发器有关的问题。

我想创建一个触发器,仅允许将特定字词(可用,不可用)用于avalability列。

怎么办?

我了解触发器是什么,但在命令序列中迷失了方向-应该在什么之后发生。

4 个答案:

答案 0 :(得分:4)

不确定此处是否确实需要触发器。另一个解决方案是在相关列上创建一个CHECK约束,例如:

ALTER TABLE TableName
ADD CONSTRAINT availability_check CHECK (availability IN ('available', 'not available'));

Demo on DB Fiddle

CREATE TABLE TableName (availability VARCHAR(20) );

ALTER TABLE TableName
ADD CONSTRAINT availability_check CHECK (availability IN ('available', 'not available'));

INSERT INTO TableName(availability) VALUES('foo');

-- Error
Msg 547 Level 16 State 0 Line 1
The INSERT statement conflicted with the CHECK constraint "availability_check". The conflict occurred in database "fiddle_325b8b256056466caf52aa4bb7467fd7", table "dbo.TableName", column 'availability'.
Msg 3621 Level 0 State 0 Line 1
The statement has been terminated.

答案 1 :(得分:4)

您可以ALTER您的表并直接将CHECK Constraint添加为

ALTER TABLE YourTableName
ADD CONSTRAINT CHK_Avalability CHECK(Avalability IN('Available', 'Not Available'));

请注意,如果表中已经插入了某些数据,但它们与CHECK Constraint不匹配且冲突,则会引发错误。

如果您还没有CREATE您的桌子,那么您可以使用

CREATE TABLE YourTableName(
  Availability VARCHAR(20) NOT NULL
    CONSTRAINT CHK_Avalability CHECK(Availability IN('Available', 'Not Available')) 
);

答案 2 :(得分:2)

有两种方法可以解决此问题。

  1. 开始:检查基于约束的方法:您可以简单地使用“检查约束”来实现。正如@GMB在他的回答中已经提到的,它使工作变得更加简单。
ALTER TABLE Table1 ADD CONSTRAINT CHK_Table1_Availability CHECK (Availability IN ('Available', 'Not Available'))
  1. 不要使用:基于触发器的方法:如果要创建触发器,则可以按如下所示创建INSTEAD OF TRIGGER。另外,您还应该创建类似的INSTEAD OF UPDATE触发器,以处理UPDATE方案。但是,这是一个circuit回的方法。请参阅所需的代码量以及相应的维护。
    CREATE TRIGGER [dbo].[tr_availability_insert]
        ON [dbo].[Table1]
        INSTEAD OF INSERT
    AS
    BEGIN
    BEGIN TRY
    BEGIN TRANSACTION
    SET NOCOUNT ON;

    IF (inserted.Availability IN ('available', 'not available'))
    BEGIN 
    INSERT INTO Table1(Id, Availability)
    SELECT Id, Availability FROM inserted
    END

    COMMIT;
    END TRY
    BEGIN CATCH

    IF @@TRANCOUNT > 0
         ROLLBACK

    RETURN;
    END CATCH
CREATE TRIGGER [dbo].[tr_availability_update]
        ON [dbo].[Table1]
        INSTEAD OF UPDATE
    AS
    BEGIN
    BEGIN TRY
    BEGIN TRANSACTION
    SET NOCOUNT ON;

    IF (inserted.Availability IN ('available', 'not available'))
    BEGIN 
    UPDATE Table1
    SET Availability = inserted.Availability
    WHERE Table1.Id = inserted.Id;
    END

    COMMIT;
    END TRY
    BEGIN CATCH

    IF @@TRANCOUNT > 0
         ROLLBACK

    RETURN;
    END CATCH

答案 3 :(得分:0)

CHECK约束是我要走的路。另一种方法是使用引用约束,即AKA主键和外键。如果在多个位置使用“可用”和“不可用”,则它比CHECK约束要好,因为您可以在多个表中实施相同的规则。这样,您可以强制保持一致性,并避免将某些表与其他值(例如“ available”和“ unavailable”)结合使用。

-- Lookup table for all possible "Availability" values
CREATE TABLE dbo.LU_Availability
(
  AvailabilityPK VARCHAR(14) NOT NULL,
  CONSTRAINT pk_LU_Availability PRIMARY KEY CLUSTERED(AvailabilityPK)
);
INSERT dbo.LU_Availability (AvailabilityPK) VALUES ('Available'),('Not Available');

-- Table with the allowable values enforced via foriegn key constraint
CREATE TABLE dbo.YourTable
(
  someId         INT IDENTITY,
  someValue      CHAR(10),
  [Availability] VARCHAR(14) NOT NULL,
  CONSTRAINT fk_AvailabilityTxt FOREIGN KEY([Availability]) 
    REFERENCES dbo.LU_Availability(AvailabilityPK)
);

INSERT dbo.YourTable ([Availability]) VALUES ('Available');     -- Succeeds
INSERT dbo.YourTable ([Availability]) VALUES ('NOT Available'); -- Succeeds
INSERT dbo.YourTable ([Availability]) VALUES ('Perhaps');       -- Fails

最后-重要的是要理解,尽管约束(CHECK,PK,FK,UNIQUE)会稍微减慢速度,但触发器是性能的杀手。这就是为什么有经验的开发人员和DBA建议在约束能够解决问题时避免使用它们。