SQLite: убедитесь, что одна запись меньше другой в качестве ограничения

#sqlite #constraints

#sqlite #ограничения

Вопрос:

Интересно, как решить эту проблему.

Я получил две таблицы

Table1 (t1_prim, t1_int) с t1_prim в качестве первичного ключа и t1_int не null .

Table2 (t2_prim1, t2prim2, t2_int) с t2_prim1 и t2_prim2 в качестве первичного ключа, а ограничение внешнего ключа t2_prim1 ссылается на t1_prim.

как я могу определить ограничение, которое гарантирует, что никто не вводит целое число в t2_int, которое больше, чем соответствующая запись в t1_int ?

Я попробовал это так (не работает, потому что вы не можете вводить подзапросы в check constraint):

 CREATE TABLE table2 
  (t2_prim1 TEXT,
  t2_prim2 INTEGER,
  t2_int INTEGER NOT NULL,
  PRIMARY KEY (t2_prim1, t2_prim2),
  FOREIGN KEY (t2_prim1) REFERENCES table1(t1_prim),
  CHECK (t2_int2 <= (SELECT t1_int2 FROM table1 WHERE t1_int1=t2_int1)));
  

И я думаю, что была бы другая проблема, если бы это работало так. Как мне проверить, что это ограничение по-прежнему заполняется при изменении t1_int?

Ответ №1:

Наконец-то нашел ответ на мой вопрос. Вы можете решить проблему с помощью триггеров. Вот рабочий пример:

 CREATE TABLE table1
  (t1_prim TEXT PRIMARY KEY,
   t1_int INTEGER NOT NULL);

CREATE TABLE table2
  (t2_prim1 TEXT,
  t2_prim2 INTEGER,
  t2_int INTEGER NOT NULL,
  PRIMARY KEY (t2_prim1, t2_prim2),
  FOREIGN KEY (t2_prim1) REFERENCES table1(t1_prim));
  

Создание триггеров для обновления и вставки:

 CREATE TRIGGER t1_int_update_constraint
BEFORE UPDATE OF t1_int ON table1
  BEGIN
    SELECT CASE 
      WHEN new.t1_int < (SELECT max(t2_int) FROM table2 WHERE t2_prim1=old.t1_prim) 
        THEN (SELECT RAISE(ABORT, 
          'Input smaller than maximum of all values for t2_int in database!'))
      END;
  END;

CREATE TRIGGER t2_int_update_constraint
BEFORE UPDATE OF t2_int ON table2
  BEGIN
    SELECT CASE 
      WHEN new.t2_int > (SELECT t1_int FROM table1 WHERE t1_prim=old.t2_prim1) 
        THEN (SELECT RAISE(ABORT, 
         'Input bigger than value in t1_int!'))
      END;
    END;

CREATE TRIGGER t2_int_insert_constraint
BEFORE INSERT ON table2
  BEGIN
    SELECT CASE 
      WHEN new.t2_int > (SELECT t1_int FROM table1 WHERE t1_prim=new.t2_prim1) 
        THEN (SELECT RAISE(ABORT, 
         'Input bigger than value in t1_int!'))
      END;
  END;
  

Если у вас теперь есть следующие таблицы:

table1

 t1_prim     t1_int
----------  ----------
one         5         
two         10   
  

table2

 t2_prim1    t2_prim2    t2_int    
----------  ----------  ----------
one         1           5         
one         2           4         
two         1           7         
two         2           5         
two         3           1         
  

Вы получаете этот вывод:

 UPDATE table1 SET t1_int=4 WHERE t1_prim='one';
  

Ошибка: ввод меньше максимального из всех значений для t2_int в базе данных!

 UPDATE table1 SET t1_int=6 WHERE t1_prim='two';
  

Ошибка: ввод меньше максимального из всех значений для t2_int в базе данных!

 UPDATE table2 SET t2_int=8 WHERE t2_prim1='one' AND t2_prim2=1;
  

Ошибка: ввод больше значения в t1_int!

 UPDATE table2 SET t2_int=11 WHERE t2_prim1='two' AND t2_prim2=2;
  

Ошибка: ввод больше значения в t1_int!

 INSERT INTO table2 VALUES ('one', 3, 6);
  

Ошибка: ввод больше значения в t1_int!

Хотя они работают отлично:

 INSERT INTO table2 VALUES ('one', 3, 6);
UPDATE table2 SET t2_int=1 WHERE t2_prim1='one' AND t2_prim2=1;
UPDATE table1 SET t1_int=8 WHERE t1_prim='two';