Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Firebird, InterBase Новый топик    Ответить
 Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Привет.

Есть таблица:
create table T (
    GROUP_ID   integer not null,
    ITEM_ID    integer not null,
    PARENT_ID  integer
);

alter table T
  add constraint PK_T
      primary key ( GROUP_ID, ITEM_ID );

Поле PARENT_ID может быть либо null, либо ссылаться на другую запись в рамках GROUP_ID, но не на саму себя.

Накладываю ограничение:
alter table T
  add constraint CHK_T check ( ( PARENT_ID is null ) or
                               ( PARENT_ID in ( select ttt.ITEM_ID
                                                  from T as ttt
                                                 where ttt.GROUP_ID = GROUP_ID
                                                   and ttt.ITEM_ID <> ITEM_ID ) ) );


Добваляю данные:
insert into T ( GROUP_ID, ITEM_ID, PARENT_ID )
       values ( 1,        1,       null      );
insert into T ( GROUP_ID, ITEM_ID, PARENT_ID )
       values ( 1,        2,       null      );
insert into T ( GROUP_ID, ITEM_ID, PARENT_ID )
       values ( 1,        3,       null      );
commit;

При попытке изменить значение поля PARENT_ID на любое, кроме null, вызывает ругань на нарушение констрейнта CHK_T.

Удаляю констрейнт CHK_T и добавляю его в виде FK и CHECK:
alter table T
  add constraint FK_T
      foreign key ( GROUP_ID, PARENT_ID ) references T ( GROUP_ID, ITEM_ID );

alter table T
  add constraint CHK_T check ( PARENT_ID <> ITEM_ID );

В таком варианте ограничения работают правильно.

Что не так в первом варианте CHK_T?

С уважением, Polesov.
8 фев 17, 14:59    [20193393]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 43937

Polesov
Что не так в первом варианте CHK_T?

Всё, начиная с самой сумасшедшей идеи запихнуть в ограничение запрос.

Posted via ActualForum NNTP Server 1.5

8 фев 17, 15:08    [20193456]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Dimitry Sibiryakov,

т.е. с виду правильный запрос в рамках ограничения работает неправильно?
8 фев 17, 15:13    [20193486]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
pastor
Member

Откуда: Калуга
Сообщений: 891
Polesov
Dimitry Sibiryakov,

т.е. с виду правильный запрос в рамках ограничения работает неправильно?


Он неправильный.

FK, PK и прочие индексы внетранзакционны в отличие от.
8 фев 17, 15:17    [20193524]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
pastor, понятно. Спасибо.
8 фев 17, 15:23    [20193567]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
kdv
Member

Откуда: iBase.ru
Сообщений: 26708
Polesov
Накладываю ограничение:

за select в check constraint надо хотя бы на пару дней лишать еды.
8 фев 17, 18:12    [20194387]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 28460

Hello, Kdv!
You wrote on 8 февраля 2017 г. 18:17:51:

Kdv
> за select в check constraint надо хотя бы на пару дней лишать еды.

От полётов отстранить.
Ста грамм не давать.
Назначить дежурным, вечным дежурным по аэродрому!
(c)

Posted via ActualForum NNTP Server 1.5

8 фев 17, 18:18    [20194409]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Ivan_Pisarevsky
Member

Откуда: НН
Сообщений: 7826
А как же традиционное "линейкой по пальцам"? по идее должно давать эффект поскорее, хотя и выветривается, пожалуй, быстрее.
8 фев 17, 18:24    [20194421]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 28460

Hello, Ivan Pisarevsky!
You wrote on 8 февраля 2017 г. 18:31:01:

Ivan Pisarevsky
> А как же традиционное "линейкой по пальцам"? по идее должно давать эффект поскорее, хотя и выветривается, пожалуй, быстрее.
не будем ограничиваться полумерами!

Картинка с другого сайта.

Posted via ActualForum NNTP Server 1.5

8 фев 17, 18:31    [20194435]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 43937

Ivan_Pisarevsky
А как же традиционное "линейкой по пальцам"? по идее должно давать эффект поскорее, хотя и
выветривается, пожалуй, быстрее.

Это смотря какая линейка. Видал я таких монстров, которые и за гильотину сойдут.

Posted via ActualForum NNTP Server 1.5

8 фев 17, 18:53    [20194510]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Апну тему.

Все же вопрос был не в том, хорошо или плохо использовать запрос в check constraint, а почему в запросе не выполняется условие.
Запрос в check такой:
select ttt.ITEM_ID
  from T as ttt
 where ttt.GROUP_ID = GROUP_ID
   and ttt.ITEM_ID <> ITEM_ID

Попытка присвоения полю ITEM_ID любого значения, отличного от null и удовлетворяющего условию ограничения, вызывает ошибку:
Operation violates CHECK constraint  on view or table.
Operation violates CHECK constraint CHK_T on view or table T.
At trigger 'CHECK_2'.


Такое впечатление, что в условии where запроса
  where ttt.GROUP_ID = GROUP_ID
    and ttt.ITEM_ID <> ITEM_ID
значения GROUP_ID и ITEM_ID берутся из контекста самого запроса, а не из контекста текущей записи.

С уважением, Polesov.
9 фев 17, 11:32    [20196072]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Ivan_Pisarevsky
Member

Откуда: НН
Сообщений: 7826
Polesov
Все же вопрос был не в том, хорошо или плохо использовать запрос в check constraint
не хорошо или плохо, а нельзя.

Polesov
значения GROUP_ID и ITEM_ID берутся из контекста самого запроса
разумеется.

используй триггер и его контекстные переменные old/new
9 фев 17, 11:40    [20196104]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Ivan_Pisarevsky,

ограничение нормально реализуется через FK и CHECK
alter table T
  add constraint FK_T
      foreign key ( GROUP_ID, PARENT_ID ) references T ( GROUP_ID, ITEM_ID );

alter table T
  add constraint CHK_T check ( PARENT_ID <> ITEM_ID );


С запросом в CHECK CONSTRAINT теперь понятно, только в документации я про это ничего не нашел.
9 фев 17, 11:47    [20196119]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Гипотетический случай.

Требуется в некой таблице хранить идентификаторы и имена системных типов. Наложить FK на таблицу RDB$TYPES нельзя, поэтому:
create table T (
    ID         integer not null primary key,
    TYPE_ID    integer,
    TYPE_NAME  char(31) character set UNICODE_FSS
);

alter table T
  add constraint CHK_T check ( ( TYPE_NAME is null ) or
                               ( TYPE_NAME in ( select RDB$TYPE_NAME
                                                  from RDB$TYPES t
                                                 where t.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
                                                   and t.RDB$TYPE = TYPE_ID ) ) );
В таком варианте ограничение работает правильно.

Изменим имена полей так, что бы они совпадали с именами системной таблицы:
create table T (
    ID             integer not null primary key,
    RDB$TYPE       integer,
    RDB$TYPE_NAME  char(31) character set UNICODE_FSS
);

alter table T
  add constraint CHK_T check ( ( RDB$TYPE_NAME is null ) or
                               ( RDB$TYPE_NAME in ( select RDB$TYPE_NAME
                                                      from RDB$TYPES t
                                                     where t.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
                                                       and t.RDB$TYPE = RDB$TYPE ) ) );
В таком варианте ограничение перестает работает.

Получается, что при совпадении имени поля его значение берется из контекста запроса, а не текущей записи.
9 фев 17, 12:12    [20196212]     Ответить | Цитировать Сообщить модератору
 Re: Непонятки с check constraint  [new]
Polesov
Member

Откуда:
Сообщений: 400
Апну тему.

Polesov
Получается, что при совпадении имени поля его значение берется из контекста запроса, а не текущей записи.

В таких случаях надо явно указывать имя таблицы:
create table TBL (
    ID             integer not null primary key,
    RDB$TYPE       integer,
    RDB$TYPE_NAME  char(31) character set UNICODE_FSS
);

alter table TBL
  add constraint CHK_TBL
      check ( ( tbl.RDB$TYPE_NAME is null ) or
              ( tbl.RDB$TYPE_NAME in ( select rdb.RDB$TYPE_NAME
                                         from RDB$TYPES rdb
                                        where rdb.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
                                          and rdb.RDB$TYPE = tbl.RDB$TYPE ) ) );
23 сен 17, 20:23    [20818267]     Ответить | Цитировать Сообщить модератору
Все форумы / Firebird, InterBase Ответить