Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Непонятки с check constraint / 15 сообщений из 15, страница 1 из 1
08.02.2017, 14:59
    #39400962
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Привет.

Есть таблица:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
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, но не на саму себя.

Накладываю ограничение:
Код: sql
1.
2.
3.
4.
5.
6.
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 ) ) );



Добваляю данные:
Код: sql
1.
2.
3.
4.
5.
6.
7.
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:
Код: sql
1.
2.
3.
4.
5.
6.
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.
...
Рейтинг: 0 / 0
08.02.2017, 15:08
    #39400976
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
PolesovЧто не так в первом варианте CHK_T?
Всё, начиная с самой сумасшедшей идеи запихнуть в ограничение запрос.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.02.2017, 15:13
    #39400982
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Dimitry Sibiryakov,

т.е. с виду правильный запрос в рамках ограничения работает неправильно?
...
Рейтинг: 0 / 0
08.02.2017, 15:17
    #39400988
pastor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
PolesovDimitry Sibiryakov,

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

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

FK, PK и прочие индексы внетранзакционны в отличие от.
...
Рейтинг: 0 / 0
08.02.2017, 15:23
    #39400996
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
pastor, понятно. Спасибо.
...
Рейтинг: 0 / 0
08.02.2017, 18:12
    #39401169
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
PolesovНакладываю ограничение:
за select в check constraint надо хотя бы на пару дней лишать еды.
...
Рейтинг: 0 / 0
08.02.2017, 18:18
    #39401174
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Hello, Kdv!
You wrote on 8 февраля 2017 г. 18:17:51:

Kdv> за select в check constraint надо хотя бы на пару дней лишать еды.
От полётов отстранить.
Ста грамм не давать.
Назначить дежурным, вечным дежурным по аэродрому!
(c)
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.02.2017, 18:24
    #39401177
Ivan_Pisarevsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
А как же традиционное "линейкой по пальцам"? по идее должно давать эффект поскорее, хотя и выветривается, пожалуй, быстрее.
...
Рейтинг: 0 / 0
08.02.2017, 18:31
    #39401179
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Hello, Ivan Pisarevsky!
You wrote on 8 февраля 2017 г. 18:31:01:

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


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.02.2017, 18:53
    #39401196
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Ivan_PisarevskyА как же традиционное "линейкой по пальцам"? по идее должно давать эффект поскорее, хотя и
выветривается, пожалуй, быстрее.

Это смотря какая линейка. Видал я таких монстров, которые и за гильотину сойдут.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
09.02.2017, 11:32
    #39401481
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Апну тему.

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


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



Такое впечатление, что в условии where запроса
Код: sql
1.
2.
  where ttt.GROUP_ID = GROUP_ID
    and ttt.ITEM_ID <> ITEM_ID

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

С уважением, Polesov.
...
Рейтинг: 0 / 0
09.02.2017, 11:40
    #39401485
Ivan_Pisarevsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
PolesovВсе же вопрос был не в том, хорошо или плохо использовать запрос в check constraintне хорошо или плохо, а нельзя.

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

используй триггер и его контекстные переменные old/new
...
Рейтинг: 0 / 0
09.02.2017, 11:47
    #39401489
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Ivan_Pisarevsky,

ограничение нормально реализуется через FK и CHECK
Код: sql
1.
2.
3.
4.
5.
6.
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 теперь понятно, только в документации я про это ничего не нашел.
...
Рейтинг: 0 / 0
09.02.2017, 12:12
    #39401507
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Гипотетический случай.

Требуется в некой таблице хранить идентификаторы и имена системных типов. Наложить FK на таблицу RDB$TYPES нельзя, поэтому:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
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 ) ) );

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

Изменим имена полей так, что бы они совпадали с именами системной таблицы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
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 ) ) );

В таком варианте ограничение перестает работает.

Получается, что при совпадении имени поля его значение берется из контекста запроса, а не текущей записи.
...
Рейтинг: 0 / 0
23.09.2017, 20:23
    #39525324
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непонятки с check constraint
Апну тему.

PolesovПолучается, что при совпадении имени поля его значение берется из контекста запроса, а не текущей записи.
В таких случаях надо явно указывать имя таблицы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
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 ) ) );
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Непонятки с check constraint / 15 сообщений из 15, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]