I have 3 tables:
NETWORK_OPERATORs;NETWORK_CELLs: each of them belongs to oneNETWORK_OPERATOR;IRIs: each of them can have either:- a Network Operator or
- a Network Cell
but one of 1) and 2) is mandatory.
In case of 1) the netOpId must exists in NETWORK_OPERATOR table;
In case of 2) the cellId+netOpId must exist in CELL table;
Here is a sample DDL code:
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")
)
In other words,
a NETWORK_CELL is itself always bound to a NETWORK_OPERATOR, so that IF a IRI has a netOpId it should be enforced to be an existing netOpId, ELSE IF a IRI has a cellId+netOpId it should be enforced to be an existing cellId+netOpId
I see 2 options:
Option 1:
Make only IRI.NETOPID NOT NULLable and add a composite FK
CREATE TABLE "IRI" (
...
"NETOPID" INTEGER NOT NULL,
"CELLID" INTEGER,
...
CONSTRAINT "IRI_CELL_FK" FOREIGN KEY ("CELLID", "NETOPID") REFERENCES "NETWORK_CELL" ("CELLID", "NETOPID")
)
(of course there will be a Unique key on "NETWORK_CELL" ("CELLID", "NETOPID"))
In other words, an IRI will have a mandatory FK relationship with a Network Operator, and an optional FK relationship with a Network Cell.
The "suspect" thing is that this "optional" FK is composed by a mandatory field and an optional one, on IRI side.
Oracle RDBMS accepts this (I just tried), but is it a good practice?
Option 2:
Same FK, like in option 1, but leave IRI.NETOPID nullable and add a custom constraint that enforce either netOpId or netOpId+cellId
I feel this solution more portable, but maybe I'm wrong.
The question
Are there better options?
What's the best practice to deal with this situation and why? I'm thinking about portability to other RDBMS, too...
Thank you