OracleSQL:自动递增取决于另一列(弱实体建模)

时间:2017-11-23 23:07:06

标签: sql database oracle database-design

我有一张名为" Project"在我的数据库和一个名为" Milestone"的表中。 "项目"的主要关键是一个名为ProjectID的列。关系"里程碑"有一个名为" Number"和一个外键指的是它所属的项目。

当我在" Milestone"中插入新条目时我想要主键" Number"要自动递增,但与新里程碑所属的项目相关。这个想法基本上如下:

if (!String.IsNullOrEmpty(Context.Request.QueryString["BSCID"]))
{
    var BSCID = Context.Request.QueryString["BSCID"];
}

在" Milestone"中插入值时,是否可以使用触发器在OracleSQL中实现这一点?表

1 个答案:

答案 0 :(得分:0)

首先,在Oracle中命名列NUMBER是一个不可思议的坏主意,因为这是基本数字类型的名称。我假设你会很聪明,而是打电话给PROJECT_LINE

您可以使用复合触发器来完成此操作。在BEFORE STATEMENT触发点中,您捕获所有项目的最大PROJECT LINE(因为当然在BEFORE STATEMENT部分您不知道您正在查看哪个项目),然后在BEFORE EACH ROW触发点为新PROJECT_LINE分配最大值+ 1,并更新项目最大值行:

CREATE OR REPLACE TRIGGER MILESTONE_TRG
  FOR INSERT ON MILESTONE
COMPOUND TRIGGER
  TYPE NUMBER_MAP IS TABLE OF NUMBER
    INDEX BY PLS_INTEGER;
  tblMAX_PROJECT_LINE  NUMBER_MAP;    -- store max PROJECT_LINE, indexed by PROJECT_ID

  BEFORE STATEMENT IS
  BEGIN
    tblMAX_PROJECT_LINE := NUMBER_MAP();

    FOR aRow IN (SELECT PROJECT_ID,
                        MAX(PROJECT_LINE) AS MAX_PROJECT_LINE
                   FROM MILESTONE
                   GROUP BY PROJECT_LINE)
    LOOP
      tblMAX_PROJECT_LINE(aRow.PROJECT_ID) := aRow.MAX_PROJECT_LINE;
    END LOOP;
  END BEFORE STATEMENT;

  BEFORE EACH ROW IS
  BEGIN
    :NEW.PROJECT_LINE := tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) + 1;
    tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) := tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) + 1;
  END AFTER EACH ROW;
END MILESTONE_TRG;

我不会保证这样做的效率。此外,多个同时INSERT可能会发生冲突。您需要在(PROJECT_ID,PROJECT_LINE)上放置PRIMARY KEY或UNIQUE约束,捕获INSERT语句中可能发生的密钥违例异常,然后重试INSERT。

祝你好运。