表选择算法

时间:2010-06-15 14:26:38

标签: sql oracle stored-procedures plsql

下面我使用的是简单示例,实际表格较大,我无法将设备存储在一个表中,我无法合并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?如何更快地执行等?

2 个答案:

答案 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;

一些建议:

  1. 使用PL / SQL异常而不是返回参数(您很容易忘记检查参数,导致很难诊断错误)
  2. 除非您需要使用自动交易,否则不要使用自主交易(在这种情况下,它们会破坏您的交易流程)。
  3. 仅在顶级调用过程/代码中使用事务进程(提交/回滚)(通常是调用应用程序,而不是PL / SQL)
  4. 不要忘记为rel1with3rel2with3上的引用列编制索引(通常您会在(d_id_1, d_id_3)上设置PK,因此您需要d_id_3上的其他索引)