Триггер SQL Server считает, что в таблице есть дубликат, когда его нет - PullRequest
0 голосов
/ 10 сентября 2018

Я новый разработчик SQL. После рекомендаций я изменил свой триггер (для этой задачи мне нужно использовать триггер, поэтому я не могу его избежать), но я изменил свой триггер. Я хочу, чтобы он предотвращал дублирование в таблице Rentals внешнего ключа BikeID, содержащегося в нем.

Это мой код на данный момент:

CREATE TRIGGER BikeNotAvailable 
ON dbo.SA_Rental
AFTER INSERT
AS
    IF EXISTS (SELECT * 
               FROM SA_Rental
               INNER JOIN inserted i ON i.BikeID = dbo.SA_Rental.BikeID)
    BEGIN
        ROLLBACK
        RAISERROR ('This bike is already being hired', 16, 1);
    END
go

Но когда я ввожу BikeID в таблицу Rentals, хотя BikeID еще не присутствует в строке, это все равно вызывает ошибку - почему? (Я также проверил это на пустой таблице, и это все еще вызывает ошибку)

Просто некоторый контекст моих данных, BikeID - это первичный ключ из таблицы 'Bike', который используется в качестве внешнего ключа для таблицы Rentals, не уверен, что это как-то связано с ошибкой.

Может кто-нибудь помочь мне исправить этот триггер, чтобы он работал.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Намного проще добиться того, чего вы хотите, - создать уникальный индекс:

CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID);

Это, конечно, предполагает , что вы удаляете строку из таблицы, когда велосипед больше не арендован (поскольку это подразумеваемая логика в вашем посте). Если это не так, то нам нужно больше деталей; что указывает на вашем столе, что аренда завершена?

Если мы предположим, , что у вас есть дата возвращения, а дата возвращения - NULL, когда велосипед еще не возвращен, тогда вы будете использовать отфильтрованный индекс, например, так :

CREATE UNIQUE INDEX BikeRented ON SA_Rental (BikeID)
WHERE ReturnedDate IS NULL;
0 голосов
/ 10 сентября 2018

Ну, так как это триггер AFTER, триггер запускается после новая запись добавляется в таблицу (по крайней мере, видимая для вашего триггера).

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

CREATE TRIGGER BikeNotAvailable ON dbo.SA_Rental
AFTER INSERT
AS
  if exists ( select * from SA_Rental
  inner join inserted i on i.BikeID=dbo.SA_Rental.BikeID
  where SA_Rental.RentalID <> i.RentalID)
  begin
    rollback
    RAISERROR ('This bike is already being hired', 16, 1);
  end
go
...