具有可空字段的复合FK

时间:2018-03-16 10:25:50

标签: oracle foreign-keys rdbms

我有3张桌子:

  • GetData S;
  • NETWORK_OPERATOR s:每个属于一个NETWORK_CELL;
  • NETWORK_OPERATOR s:每个人都可以

    1. 网络运营商
    2. 网络单元

但1)和2)中的一个是强制性的。

如果1)IRI必须存在于netOpId表中;

如果是2)NETWORK_OPERATOR + cellId必须存在于netOpId表中;

以下是DDL代码示例:

CELL

换句话说

CREATE TABLE "NETWORK_OPERATOR" ( "NETOPID" INTEGER NOT NULL, "NAME" VARCHAR2(20), CONSTRAINT "NETWORK_OPERATOR_PK" PRIMARY KEY ("NETOPID") ) CREATE TABLE "NETWORK_CELL" ( "CELLID" INTEGER NOT NULL, "NETOPID" INTEGER NOT NULL, "NAME" VARCHAR2(20), CONSTRAINT "NETWORK_CELL_PK" PRIMARY KEY ("CELLID"), CONSTRAINT "CELL_NETOPS_FK" FOREIGN KEY ("NETOPID") REFERENCES "NETWORK_OPERATOR" ("NETOPID") ) CREATE TABLE "IRI" ( "IRIID" INTEGER NOT NULL, "NETOPID" INTEGER, "CELLID" INTEGER, "NAME" VARCHAR2(20), CONSTRAINT "IRI_PK" PRIMARY KEY ("IRIID"), CONSTRAINT "IRI_NETOPS_FK" FOREIGN KEY ("NETOPID") REFERENCES "NETWORK_OPERATOR" ("NETOPID") ) 本身始终绑定到NETWORK_CELL,因此 IF a NETWORK_OPERATOR的{​​{1}}应该强制为IRI现有netOpId ELSE IF netOpIdIRI + cellId,应强制其为现有netOpId + cellId

我看到两个选项:

选项1:

仅使netOpId能够并添加复合FK

IRI.NETOPID NOT NULL

(当然 CREATE TABLE "IRI" ( ... "NETOPID" INTEGER NOT NULL, "CELLID" INTEGER, ... CONSTRAINT "IRI_CELL_FK" FOREIGN KEY ("CELLID", "NETOPID") REFERENCES "NETWORK_CELL" ("CELLID", "NETOPID") 上有一个唯一键)

换句话说,IRI将与网络运营商建立强制性的FK关系,并与网络单元建立可选的FK关系。

“可疑”的事情是,这个“可选的”FK由IRI方面的必填字段和可选字段组成。

Oracle RDBMS接受了这个(我刚试过),但这是一个好习惯吗?

选项2:

与选项1中的FK相同,但保留"NETWORK_CELL" ("CELLID", "NETOPID")可空,并添加一个自定义约束,强制执行 IRI.NETOPID {{1 }} + netOpId

我觉得这个解决方案更便携,但也许我错了。

问题

有更好的选择吗?

处理这种情况的最佳做法是什么?为什么? 我也在考虑其他RDBMS的可移植性......

谢谢

2 个答案:

答案 0 :(得分:2)

您的选项1没问题。默认FK(外键)声明模式MATCH SIMPLE(通常是唯一实现的)工作方式,带有任何NULL的FK子行值满足其约束。所以你可以拥有IRI FK(netid)& (netid,cellid) - 加上netid NOT NULL。 (您似乎已经忘记了第一个IRI中的NOT NULL,但不是第二个。)

然后列对的唯一情况是(非null,null)& (非null,非null)。必须存在一个netid;一个非null的cellid必须与那个netid&一个NULL cellid就可以了。

答案 1 :(得分:0)

根据我的理解,一个解决方案可能是这个:

CREATE TABLE IRI (
  IRIID INTEGER NOT NULL,
  NETOPID INTEGER,
  CELLID INTEGER,
  NAME VARCHAR2(20),
  CONSTRAINT IRI_PK PRIMARY KEY (IRIID),
  CONSTRAINT IRI_NETOPS_FK FOREIGN KEY (NETOPID) REFERENCES NETWORK_OPERATOR (NETOPID),
  CONSTRAINT IRI_CELLS_FK FOREIGN KEY (CELLID) REFERENCES NETWORK_CELL (CELLID),
  CONSTRAINT IRI_CELL_OR_NETOP CHECK ( NVL(NETOPID, CELLID) IS NOT NULL )
)

如果您希望强制只设置值,则可以使用

CHECK ( NVL(NETOPID, CELLID) IS NOT NULL AND NOT (NETOPID IS NOT NULL AND CELLID IS NOT NULL) )

CHECK ( NVL(NETOPID, CELLID) IS NOT NULL AND NETOPID||CELLID IN (NETOPID, CELLID) )

CHECK ( (NETOPID IS NULL AND CELLID IS NOT NULL) OR (NETOPID IS NOT NULL AND CELLID IS NULL) )