2

Я пытаюсь создать простую базу данных регистрации гостиничного номера в качестве учебного упражнения.Альтернатива использованию подзапроса внутри ограничения CHECK?

CREATE TABLE HotelReservations 
(
    roomNum INTEGER NOT NULL, 
    arrival DATE NOT NULL, 
    departure DATE NOT NULL, 
    guestName CHAR(30) NOT NULL, 

    CONSTRAINT timeTraveler CHECK (arrival < departure) /* stops time travelers*/ 
    /* CONSTRAINT multipleReservations CHECK (my question is about this) */ 

    PRIMARY KEY (roomNum, arrival) 
); 

У меня возникли проблемы с указанием ограничения, которое не позволяет вставить новый номер комнаты, которая еще не освобожденной. Например (ниже), гость «B» проверяет в комнате 123 до «A».

INSERT INTO HotelStays(roomNum, arrival, departure, guestName) 
VALUES 
    (123, date("2017-02-02"), date("2017-02-06"), 'A'), 
    (123, date("2017-02-04"), date("2017-02-08"), 'B'); 

Этого нельзя допускать, но я не уверен, как написать это ограничение. Моя первая попытка состояла в том, чтобы проверить подзапрос, но у меня возникли проблемы с поиском правильного подзапроса, потому что я не знаю, как получить доступ к значению «roomNum» новой вставки для выполнения подзапроса. Затем я также понял, что большинство систем SQL даже не разрешают подзапросы внутри проверки.

Так как же я должен написать это ограничение? Я читал некоторые о триггерах, которые, похоже, могут решить эту проблему, но действительно ли это единственный способ сделать это? Или я просто плотный и отсутствует очевидный способ написать ограничение?

+0

Вы задаете несколько вопросов, и они все дубликаты. Пожалуйста, сначала имейте это в виду, с и без stackoverflow, с и без SQLite. Например, какие SQL-базы данных поддерживают подзапросы в CHECK, Sub-запросы в контрольном ограничении, создание условного SQL-триггера в SQLite, перекрытие контрольного ограничения диапазона дат. Вам нужны триггеры. Повторите свой конкретный запрос ограничения, чтобы увидеть мой ответ re [Найти диапазон дат в одной таблице] (http://stackoverflow.com/a/34327197/3404097). – philipxy

+0

Вы не можете делать то, что хотите, с контрольным ограничением - если вы не используете определенную пользователем функцию. Но если вы собираетесь это сделать, вы можете использовать триггер или хранимую процедуру в любом случае. –

ответ

2

documentation действительно говорит:

Выражение проверочное ограничение не может содержать подзапрос.

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

Существует специальный mechanism to access the new row inside the trigger:

И КОГДА положение и триггерные действия могут получить доступ к элементам строки вставляются, удалены или обновлены с использованием ссылки вида «колонного имя NEW» и "OLD. имя-столбца", где имя-столбца - это имя столбца из таблицы, с которым связан триггер.

CREATE TRIGGER multiple_reservations_check 
BEFORE INSERT ON HotelReservations 
BEGIN 
    SELECT RAISE(FAIL, "reservations overlap") 
    FROM HotelReservations 
    WHERE roomNum = NEW.roomNum 
     AND departure > NEW.arrival 
     AND arrival < NEW.departure; 
END;