Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6656
Здравствуйте, есть таблица с двумя внешними ключами.
create table test
(
   ...
   FK1 integer NULL,
   FK2 integer NULL,
   ...
)

Мне нужно, чтобы один из них (FK1 либо FK2) всегда был не NULL и никогда бы не было, что оба NULL либо NOT NULL.
Короче, чтобы один из ключей и только один всегда был заполнен.

Наметил возможный способ:
- проверка триггером

Но, возможно, есть какой-нибудь способ лучше, типа CONSTRAINT'a на два поля сразу?
Спасибо.

(Oracle 9.2)
27 ноя 08, 13:18    [6494472]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
-Попрошайка-
Guest
Всегда не понимал людей, которые отказываются от функционала СУБД и пытаются протягивать зубы через задний проход.
27 ноя 08, 13:23    [6494504]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6656
-Попрошайка-
... которые отказываются от функционала СУБД...


нет, я его ищу :)
27 ноя 08, 13:25    [6494523]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Alexander Konakov
Member

Откуда:
Сообщений: 1027
Кроик Семён,

CHECK CONSTRAINT типа (column1 IS NULL AND column2 IS NOT NULL) OR (column1 IS NOT NULL AND column2 IS NULL)
27 ноя 08, 13:27    [6494546]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6656
Alexander Konakov
CHECK CONSTRAINT типа (column1 IS NULL AND column2 IS NOT NULL) OR (column1 IS NOT NULL AND column2 IS NULL)


я не нашел в справке к CREATE TABLE, что можно делать CONSTRAINT сразу на 2 поля таблицы, хотя искал.
Оттого и вопрос, собственно, возник.

Но раз Вы пишете, пройдусь и по интернету. Спасибо.
27 ноя 08, 13:31    [6494577]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6656
Кроик Семён
Но раз Вы пишете, пройдусь и по интернету. Спасибо.


сразу нашел, кажется, то что нужно:

ALTER TABLE table_name
ADD CONSTRAINT cons_name CHECK (Spalte1 is NOT NULL OR Spalte2 is NOT NULL);
27 ноя 08, 13:36    [6494622]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Жук в муравейнике
Member

Откуда:
Сообщений: 717
Check constraint

alter table  test 
     add  constraint chk_test
      check ((fk1 + fk2) is null and coalesce(fk1,fk2) is not null)
27 ноя 08, 13:36    [6494628]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Жук в муравейнике
Member

Откуда:
Сообщений: 717
Кроик Семён,

оба not null у тебя пройдут
27 ноя 08, 13:37    [6494639]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
vetrov
Member

Откуда:
Сообщений: 4
Как вариант
CREATE OR REPLACE TRIGGER scott.test_fk
BEFORE INSERT OR UPDATE
ON scott.TEST
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
  
   
     if :new.fk1 is null and :new.fk2 is null THEN
       RAISE_APPLICATION_ERROR (-20202, 'Один из ключей должен быть заполнен обязательно!!!!!');
       end if;
END test_fk;
27 ноя 08, 13:37    [6494641]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Elic
Member

Откуда:
Сообщений: 29976
Жук в муравейнике
check ((fk1 + fk2) is null and coalesce(fk1,fk2) is not null)
check(nvl2(fk1, 1, 0) + nvl2(fk2, 1, 0) = 1)
27 ноя 08, 13:48    [6494740]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Elic
Member

Откуда:
Сообщений: 29976
vetrov
     if :new.fk1 is null and :new.fk2 is null THEN
Мало того, что методы не те, так ещё и неправильные.
Сидел бы дома и не высовывался
27 ноя 08, 13:51    [6494775]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
vetrov
Member

Откуда:
Сообщений: 4
Elic
vetrov
     if :new.fk1 is null and :new.fk2 is null THEN
Мало того, что методы не те, так ещё и неправильные.
Сидел бы дома и не высовывался

создай, проверь, потести, отпишись
27 ноя 08, 13:54    [6494801]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Жук в муравейнике
Member

Откуда:
Сообщений: 717
Elic
Жук в муравейнике
check ((fk1 + fk2) is null and coalesce(fk1,fk2) is not null)
check(nvl2(fk1, 1, 0) + nvl2(fk2, 1, 0) = 1)

Куул !
27 ноя 08, 13:59    [6494848]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6656
vetrov
уважаемый гуру, анука распиши, что не правильно в тригере... почитаю ума рузума наберусь...


я не гуру :) но предположу, не правильно вообще использовать триггер в данном случае.
Я намекал на это еще в вопросе.

А так, спасибо всем ответившим.
27 ноя 08, 14:10    [6494944]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
полотенчик
Member

Откуда:
Сообщений: 226
Elic
Жук в муравейнике
check ((fk1 + fk2) is null and coalesce(fk1,fk2) is not null)
check(nvl2(fk1, 1, 0) + nvl2(fk2, 1, 0) = 1)
check ( coalesce(fk1,fk2) in (fk1,fk2) )
27 ноя 08, 14:12    [6494963]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Alexander Konakov
Member

Откуда:
Сообщений: 1027
Доктор, почему меня все игнорируют? :)

CREATE TABLE t ( c1 NUMBER, c2 NUMBER );

ALTER TABLE t ADD CONSTRAINT cnstrt_chk CHECK ((c1 IS NULL AND c2 IS NOT NULL) or (c1 IS NOT NULL AND c2 IS NULL));

INSERT INTO t VALUES (null, null); -- хрена
INSERT INTO t VALUES (1, null);
INSERT INTO t VALUES (null, 1);
INSERT INTO t VALUES (1, 1); -- хрена
27 ноя 08, 14:33    [6495156]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Elic
Member

Откуда:
Сообщений: 29976
Alexander Konakov
Доктор, почему меня все игнорируют? :)
Потучто ты чересчур многословен :)
27 ноя 08, 14:35    [6495162]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Alexander Konakov
Member

Откуда:
Сообщений: 1027
Да, с NVL2 вариант прикольный - но с непривычки не сразу воспринимаемый :)
27 ноя 08, 14:35    [6495163]     Ответить | Цитировать Сообщить модератору
 Re: Как контролировать, что только одно из 2-х полей заполнено (NOT NULL)  [new]
Elic
Member

Откуда:
Сообщений: 29976
Совершенно случайно обнаружил, что сверхдоблестные блюстители переусердствовали, в результате чего в теме может сложится впечатление, что пост тряпочки не вызвал возражений.
+
From: =?windows-1251?B?RWxpYw==?= <nospam@sql.ru>
Newsgroups: sqlru.oracle
References: <6494472@sql.ru>
In-Reply-To: <6494472@sql.ru>
Subject: =?windows-1251?B?UmU6IMrg6iDq7u3y8O7r6PDu4uDy/Cwg9/LuIPLu6/zq7iDu5O3uIOjnIDIt9SDv7uvl6SDn4O/u6+3l7e4gKE5PVCBOVUxMKQ==?=
Date: Thu, 27 Nov 08 11:15:03 GMT
Lines: 1
Message-ID: <6495003@sql.ru>
MIME-Version: 1.0
Content-Type: text/html; charset="windows-1251";
Content-Transfer-Encoding: 8bit
X-Old-Xref: sql.ru sqlru.oracle 606888
Path: sql.ru

<HTML><BODY><TABLE WIDTH=100% BORDER=0 STYLE="font: 13px Arial; border : 1px solid;background-color:#F9F9F9;"><TR><TD align=LEFT style="background-color:#F2F2F2">Автор: <a href="https://www.sql.ru/forum/memberinfo.aspx?mid=24806">Elic</A></TD></TR><TR><TD style=" padding:5px"><TABLE BORDER=0 bgcolor=#DDDDDD cellspacing=0 cellpadding=4 style="border: solid 1px #888888; margin :10px"><TR HEIGHT=1><TD STYLE="font: bold 11px Arial;">полотенчик</TD></TR><TR><TD style="font : xx-small Verdana,Arial; padding : 7px" bgcolor=#EFEFFF><PRE STYLE=" margin: 1px; font-family: monospace; font-size: 10pt; border-top:1px solid #CCB67E; border-bottom:1px solid #FFFEFA;border-right:1px solid #FFFEFA; border-left:1px solid #CCB67E; margin-top:5px; background-color: #FFFAED; padding : 9px;"><font color=blue>check</font> ( coalesce(fk1,fk2) <font color=blue>in</font> (fk1,fk2) )</PRE></TD></TR></TABLE>Тоже на ручнике? <img valign="middle" src="https://www.sql.ru/forum/images/laugh.gif"></TD></TR><TR><TD align=right style="background-color:#EEEEEE"><a href="https://www.sql.ru/forum/actualthread.aspx?tid=618180">Тема</a>  <a href="https://www.sql.ru/forum/actualpost.aspx?tid=618180">Ответить</a> <a href="https://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=618180&msg=6495003">Сообщение</a></TD></TR></TABLE></BODY></HTML>
Для заполнения этого пробела повторяю свои возвражения без купюр, ибо не вижу ничего противоправного.
______________________________________________________________________________________________________


полотенчик
check ( coalesce(fk1,fk2) in (fk1,fk2) )
Тоже на ручнике?
16 дек 08, 15:44    [6578133]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить