[英]Oracle sql constraint questions
I'm having problems with creating a oracle sql script. 我在创建oracle sql脚本时遇到问题。 How do I create these two constraints?
如何创建这两个约束?
Here is what I have so far: 这是我到目前为止:
create table Employee(
Id int primary key,
Name varchar(15) not null,
VID int,
FID int
);
You can come very close to what you want without a trigger. 你可以在没有触发器的情况下非常接近你想要的东西。
You can use a check constraint for the first: 您可以对第一个使用检查约束:
alter table Employee add constraint chk_vid_fid
check (vid is not null or fid is null);
You can do the second using a unique constraint: 您可以使用唯一约束执行第二个操作:
create unique index unq_Employee_vid on
Employee(case when vid is null then -1 else id end);
This formulation assumes that id
is non-negative, as most ids usually are. 这个公式假设
id
是非负的,因为大多数id通常都是。 If you do use the full range of integer values, then I would be explicit with a string: 如果你确实使用了整个范围的整数值,那么我将使用字符串显式:
create unique index unq_Employee_vid on
Employee(case when vid is null then 'null vid' else cast(id as varchar2(255)) end);
This guarantees at most one row where vid
is null, rather than exactly one row. 这可以保证在最一排,其中
vid
是空的,而不是一行 。 You cannot easily have a constraint that guarantees that exactly one row has a value, because empty tables do not match the condition -- and tables are empty when they are created. 您不能轻易地拥有一个约束来保证只有一行具有值,因为空表与条件不匹配 - 并且表在创建时为空。
Here is how you can enforce your requirement - to have exactly one row with VID is NULL
. 这里是你如何执行你的要求-具有完全相同一行与
VID is NULL
。 As I said in my Comment under your original question (and Gordon said as well in his accepted Answer), you cannot do this just with constraints. 正如我在你的原始问题的评论中所说(戈登在他接受的答案中也说过),你不能仅仅通过约束来做到这一点。 However, you can do it with a materialized view.
但是,您可以使用物化视图来执行此操作。 Note that you must create the MV with
refresh fast on commit
, and that requires certain things for the materialized view log on the base table. 请注意,您必须
refresh fast on commit
创建MV,并且需要基表上的物化视图日志的某些内容。
Also: If you try everything exactly as written, the constraint on the MV will fail (of course, because the base table will be empty, so there will be no row where VID
is NULL
). 另外:如果你完全按照所写的方式尝试所有内容,MV上的约束将失败(当然,因为基表将为空,所以不存在
VID
为NULL
行)。 Add rows to the base table, of which exactly one has NULL
for VID
, then commit
the transaction, and then execute the alter table
command to add the constraint to the MV. 向基表添加行,其中一行对
VID
只有一个NULL
,然后commit
事务,然后执行alter table
命令将约束添加到MV。 From that point on, a transaction on the base table (consisting of one or more insert
, delete
, update
or merge
statements, followed by one commit
) will go through if and only if it leaves exactly one row with NULL
in the VID
column. 从那时起,基表上的事务(由一个或多个
insert
, delete
, update
或merge
语句组成,后跟一个commit
)将通过,当且仅当它在VID
列中只留下一行NULL
时。
One oddity to keep in mind: even though there is an ALTER MATERIALIZED VIEW
statement in Oracle SQL, to add a constraint on a MV we must use the ALTER TABLE
statement (with the MV's name), not ALTER MATERIALIZED VIEW
. 需要记住的一个奇怪之处是:即使Oracle SQL中有
ALTER MATERIALIZED VIEW
语句,要在MV上添加约束,我们必须使用ALTER TABLE
语句(使用MV的名称),而不是使用ALTER MATERIALIZED VIEW
。
Note that I used the name t_Employee
for the base table, as I already had a table EMPLOYEE
and I don't want to mess with my existing objects. 请注意,我使用名称
t_Employee
作为基表,因为我已经有一个表EMPLOYEE
,我不想弄乱现有的对象。
create table t_Employee(
Id int primary key,
Name varchar(15) not null,
VID int,
FID int
);
alter table t_Employee add constraint chk_vid_fid
check (vid is not null or fid is null)
;
create materialized view log on t_Employee
with rowid
(VID)
including new values
;
create materialized view mv_Employee
refresh fast on commit
as select count(*) ct
from t_Employee
where VID is null
;
alter table mv_Employee add constraint chk_vid_ct
check (ct = 1)
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.