Мы не можем создавать ограничения на типы объектов. Это только одна из причин, почему использование типов объектов для сохранения (а не в программах на PL / SQL) не рекомендуется.
Однако можно обеспечить уникальность в триггере. Этот создает набор записей (то есть один экземпляр уникальных значений) и сравнивает его с фактической вложенной таблицей. Если число отличается, то у вложенной таблицы есть повторяющиеся значения.
Настройка:
create or replace type speciality_t as object (name varchar2(30));
/
create or replace type specialities_nt as table of speciality_t;
/
create table doctors (
doctor_id number primary key
, works_in specialities_nt
)
nested table works_in store as works_in_nt ;
Триггер:
create or replace trigger ck_speciality
before insert or update on doctors
for each row
declare
dummy1 specialities_nt;
dummy2 number;
begin
-- all the unique values for WORKS_IN
select set(:new.works_in)
into dummy1
from dual;
-- count diff
select m - n
into dummy2
from ( select count(*) as m from table(:new.works_in)) t1
cross join ( select count(*) as n from table(dummy1)) t2;
-- hurl if the difference is not zero
if dummy2 != 0 then
raise_application_error (-20042, 'duplicate speciality');
end if;
end;
/
Чтобы было ясно, я не думаю, что использование вложенных таблиц является лучшим способом хранения этих данных: правильный подход - это таблица ссылок SPECIALTY и таблица пересечений DOCTOR_SPECIALITY для сохранения того, какие врачи практикуют по каким специальностям.
Однако я заинтригован, узнав, может ли кто-нибудь придумать более элегантное решение, чем приведенное выше.