SQL约束:两个属性,至少一个外键匹配相同table
SQL constraint: two attributes, at least one foreign key match on same table
我有一个公司拥有的 table 个 phone 个号码,以及一个 table 个 phone 个通话记录。每个呼叫记录都包括(非空)源和目标号码。我得到了完整性约束,即允许源号码或目标号码(但不能同时是两者)是不在 phone 号码 table 中的号码(因为它们是不属于此号码的号码公司)。换句话说,我需要确保其中至少有一个是 phone 数字 table.
的外键
create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
primary key (URID)
);
以下听起来像我想要的但无效 SQL:
constraint call_constraint check (
foreign key (c_src) references phonenumber (phonenum) or
foreign key (c_dst) references phonenumber (phonenum)
)
有没有办法在 DDL 中指定它?如果没有,我将如何编写触发器来执行此操作?
已编辑:
这是另一个使用 DDL 而不是使用触发器的想法:
create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
创建一个函数来验证外键 "by hand"。
CREATE OR REPLACE FUNCTION call_check(p_src NUMBER, p_dst NUMBER) RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
FOR x IN (SELECT COUNT(*) c
FROM (SELECT 1
FROM phonenumber
WHERE phonenum = p_src
UNION ALL
SELECT 1
FROM phonenumber
WHERE phonenum = p_dst)) LOOP
IF x.c>=1 AND x.c <= 2 THEN
RETURN 'OK';
END IF;
END LOOP;
RETURN 'NOK';
END;
如果您使用的是 11g 及更高版本,请添加虚拟列并在该列上添加检查
--drop table call_record
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
call_check_col GENERATED ALWAYS AS (call_check(c_src, c_dst)),
primary key (URID)
);
ALTER TABLE call_record ADD CONSTRAINT call_check_con CHECK (call_check_col='OK');
我们来测试一下
SQL> INSERT INTO phonenumber VALUES ('123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C1', '123', '321');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C3', '123', '123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321');
INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321')
ORA-02290: check constraint (TST.CALL_CHECK_CON) violated
我有一个公司拥有的 table 个 phone 个号码,以及一个 table 个 phone 个通话记录。每个呼叫记录都包括(非空)源和目标号码。我得到了完整性约束,即允许源号码或目标号码(但不能同时是两者)是不在 phone 号码 table 中的号码(因为它们是不属于此号码的号码公司)。换句话说,我需要确保其中至少有一个是 phone 数字 table.
的外键create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
primary key (URID)
);
以下听起来像我想要的但无效 SQL:
constraint call_constraint check (
foreign key (c_src) references phonenumber (phonenum) or
foreign key (c_dst) references phonenumber (phonenum)
)
有没有办法在 DDL 中指定它?如果没有,我将如何编写触发器来执行此操作?
已编辑: 这是另一个使用 DDL 而不是使用触发器的想法:
create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
创建一个函数来验证外键 "by hand"。
CREATE OR REPLACE FUNCTION call_check(p_src NUMBER, p_dst NUMBER) RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
FOR x IN (SELECT COUNT(*) c
FROM (SELECT 1
FROM phonenumber
WHERE phonenum = p_src
UNION ALL
SELECT 1
FROM phonenumber
WHERE phonenum = p_dst)) LOOP
IF x.c>=1 AND x.c <= 2 THEN
RETURN 'OK';
END IF;
END LOOP;
RETURN 'NOK';
END;
如果您使用的是 11g 及更高版本,请添加虚拟列并在该列上添加检查
--drop table call_record
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
call_check_col GENERATED ALWAYS AS (call_check(c_src, c_dst)),
primary key (URID)
);
ALTER TABLE call_record ADD CONSTRAINT call_check_con CHECK (call_check_col='OK');
我们来测试一下
SQL> INSERT INTO phonenumber VALUES ('123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C1', '123', '321');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C3', '123', '123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321');
INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321')
ORA-02290: check constraint (TST.CALL_CHECK_CON) violated