简体   繁体   English

Oracle sql约束问题

[英]Oracle sql constraint questions

I'm having problems with creating a oracle sql script. 我在创建oracle sql脚本时遇到问题。 How do I create these two constraints? 如何创建这两个约束?

  1. If VID is null then FID has to be null as well (VID = null -> FID = null) 如果VID为null,那么FID也必须为空(VID = null - > FID = null)
  2. There has to be exactly one row where VID is null which also means that FID has to be null because of 1. 必须只有一行VID为空,这也意味着FID必须为1,因为1。

Here is what I have so far: 这是我到目前为止:

create table Employee(
Id int primary key,
Name varchar(15) not null,
VID int,
FID int

);

Employee 雇员

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上的约束将失败(当然,因为基表将为空,所以不存在VIDNULL行)。 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. 从那时起,基表上的事务(由一个或多个insertdeleteupdatemerge语句组成,后跟一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM