Триггер, который исключает некоторые слова - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть вопрос, связанный с триггерами базы данных в T-SQL.

Я хочу создать триггер, который допускает только определенные слова (доступно, недоступно) в столбец avalability.

Как это можно сделать?

Я понимаю, что такое триггер, но потерян в последовательности команд - что должно произойти после чего.

Ответы [ 4 ]

4 голосов
/ 19 сентября 2019

Вы можете 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')) 
);
4 голосов
/ 19 сентября 2019

Не уверен, что здесь действительно нужен триггер.Другим решением было бы создать ограничение CHECK для соответствующего столбца, например:

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

Демонстрация на 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.
2 голосов
/ 19 сентября 2019

Есть два подхода к проблеме.

  1. GO FOR: ПРОВЕРЬТЕ ПОДХОД НА ОСНОВЕ : Вы можете достичь этого, просто используя CHECK Constraint.Это упрощает работу, как @GMB уже упоминал в своем ответе.
ALTER TABLE Table1 ADD CONSTRAINT CHK_Table1_Availability CHECK (Availability IN ('Available', 'Not Available'))
НЕ ИДЕТ ДЛЯ: ПОДХОДА НА ОСНОВЕ TRIGGER : Если вы хотите создать триггер, вы можете создать INSTEAD OF TRIGGER, как указано ниже.Кроме того, вы должны также создать аналогичный триггер INSTEAD OF UPDATE, чтобы позаботиться о сценариях UPDATE.Но это обходной подход.См количество требуемого кода, соответствующее обслуживание.
    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
0 голосов
/ 19 сентября 2019

Ограничение CHECK - это мой путь.Другой подход заключается в использовании ссылочных ограничений, первичных и внешних ключей AKA.Если «доступно» и «недоступно» используется в нескольких местах, это будет лучше, чем ограничение CHECK, поскольку вы можете применять одинаковые правила для нескольких таблиц.Таким образом, вы можете обеспечить согласованность и избежать появления некоторых таблиц с другими значениями, такими как «доступно» и «недоступно».

-- 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) немного замедлит работу, триггеры - убийцы производительности.Вот почему опытные разработчики и администраторы баз данных предлагают избегать их, когда ограничение сработает.

...