下面我使用的是简单示例,实际表格较大,我无法将设备存储在一个表中,我无法合并device1和device2表。
我有三个表:device1,device2,computer(device3),device1和device2具有来自相同序列的id,device3是计算机。表device3可以与device1和device2(多对多)连接,所以我有两个关系表:rel1with3和rel2with3。
CREATE SEQUENCE device_1or2;
CREATE SEQUENCE device_3;
CREATE TABLE device1
( d_id NUMBER, d_data VARCHAR2(20)
, CONSTRAINT device1_pk PRIMARY KEY (d_id));
CREATE TABLE device2
( d_id NUMBER, d_data VARCHAR2(20)
, CONSTRAINT device2_pk PRIMARY KEY (d_id));
CREATE TABLE computer
( d_id NUMBER, d_data VARCHAR2(20)
, CONSTRAINT device3_pk PRIMARY KEY (d_id));
CREATE TABLE rel1with3
( d_id_1 NUMBER, d_id_3 NUMBER
, CONSTRAINT rel13_fk_1 FOREIGN KEY (d_id_1) REFERENCES device1 (d_id)
, CONSTRAINT rel13_fk_3 FOREIGN KEY (d_id_3) REFERENCES computer (d_id)
);
CREATE UNIQUE INDEX I_REL_13 ON rel1with3 (d_id_1, d_id_3);
CREATE TABLE rel2with3
( d_id_2 NUMBER, d_id_3 NUMBER
, CONSTRAINT rel23_fk_2 FOREIGN KEY (d_id_2) REFERENCES device2 (d_id)
, CONSTRAINT rel23_fk_3 FOREIGN KEY (d_id_3) REFERENCES computer (d_id)
);
CREATE UNIQUE INDEX I_REL_23 ON rel2with3 (d_id_2, d_id_3);
我想创建存储过程,其中有两个参数(device1或device2作为第一个参数,计算机作为第二个参数)和添加/删除关系(插入/删除关系表中的行)。
CREATE OR REPLACE PROCEDURE Add_Relation
( COMPUTER NUMBER
, DEVICE NUMBER
, ERR OUT NUMBER
) IS
PRAGMA AUTONOMOUS_TRANSACTION;
device_data VARCHAR2(20);
BEGIN
-- detect which device it is, insert record
-- stored procedure, the same for both device type, BUT uses device data from additional table field
WRITE_LOG(device, device_data, computer);
COMMIT;
EXCEPTION
WHEN OTHERS THEN ERR := TO_CHAR(SQLCODE);
END;
问题是:如何更好地组织这个?使用其他功能?使用IF-ELSE?如何更快地执行等?
答案 0 :(得分:1)
我只使用一个序列对象并拥有一个设备表。在设备表中,我会这样:
CREATE TABLE device
(
ID NUMBER NOT NULL PRIMARY KEY
, device_name VARCHAR2(100) NOT NULL
, device_type VARCHAR2(100) NOT NULL
, parent_device_id NUMBER NULL
, child_device_id NUMBER NULL
);
alter table device
add constraint FK1 foreign key (parent_device_id)
references device (ID);
alter table device
add constraint FK2 foreign key (child_device_id)
references device (ID);
对于类型3(多对多)的设备,我将拥有parent_device_id和child_device_id的值(这些将是设备3连接到的设备)。如果没有与此设备相关的任何设备,则这些列对于给定设备将为空。
如果有一个比父母/孩子更好的名字,你可以使用任何适当的。我们的想法是,您只需将设备存储在一个表中,并相应地映射关系。
parent_device_id和child_device_id将外键返回到id列上的设备表,这样可以确保您永远不会“孤立”任何设备记录。
您可以在插入设备记录时使用相同的序列对象生成新的ID。
答案 1 :(得分:1)
我只是尝试插入rel1with3
,如果失败则尝试使用rel2with3
:
CREATE OR REPLACE PROCEDURE Add_Relation(computer NUMBER, device NUMBER) IS
device_data VARCHAR2(20);
parent_key_not_found EXCEPTION;
PRAGMA EXCEPTION_INIT(parent_key_not_found, -2291);
BEGIN
BEGIN
INSERT INTO rel1with3 (d_id_1, d_id_3) VALUES (computer, device);
device_data := 'device1';
EXCEPTION
WHEN parent_key_not_found THEN
INSERT INTO rel2with3 (d_id_2, d_id_3) VALUES (computer, device);
device_data := 'device2';
END;
WRITE_LOG(device, device_data, computer);
END;
一些建议:
rel1with3
和rel2with3
上的引用列编制索引(通常您会在(d_id_1, d_id_3)
上设置PK,因此您需要d_id_3
上的其他索引)