【问题标题】:Oracle : Autopopulate foreign key if parent table referenced column has valuesOracle:如果父表引用的列具有值,则自动填充外键
【发布时间】:2012-07-03 14:41:52
【问题描述】:

这可能是个愚蠢的问题,但不知何故我无法绕过它。

我有表statuslogs,这两个表都有jobId 列。 jobId 是基于序列生成的,所以我想将sequence generated jobIdlogs 表添加到status 页面。

我在 status 表中创建了引用 logs 表的 jobId 列的外键,但 status 表中未填充 jobId 值。

jobId 使用序列在logs 中自动生成时,如何在status 表中自动填充jobId

更新

<id name="jobid"
        column="JOBID"
        type="long"
        unsaved-value="-1">
      <generator class="native">
            <param name="sequence">ID_SEQ</param>
        </generator>
    </id>

这是如何为status 页面生成 id,建议我需要使用 ID_SEQ.curval 但我如何在休眠中做到这一点,知道吗?

类似

<id name="id"
        column="ID"
        type="long"
        unsaved-value="-1">
      <generator class="native">
            <param name="sequence">ID_SEQ.curval</param>
        </generator>
    </id>

想法?

【问题讨论】:

    标签: sql oracle hibernate foreign-keys


    【解决方案1】:

    这取决于您如何使用序列来填充此列,但是当您在status 表中填充jobID 时,您很可能希望使用序列的currval

    在最简单的情况下,你有两个表和一个序列

    SQL> create table logs(
      2    jobID number primary key
      3  );
    
    Table created.
    
    SQL> create table status (
      2    jobID number references logs(jobID)
      3  );
    
    Table created.
    
    SQL> create sequence jobID_seq;
    
    Sequence created.
    

    插入logs 时,使用序列的nextval,插入status 时使用序列的currvalcurrval 为您提供会话的最新值,因此您不会看到给其他会话的 currval 风险

    SQL> insert into logs values( jobID_seq.nextval );
    
    1 row created.
    
    SQL> insert into status values( jobID_seq.currval );
    
    1 row created.
    
    SQL> select * from logs;
    
         JOBID
    ----------
             5
    
    SQL> select * from status;
    
         JOBID
    ----------
             5
    

    如果您使用触发器(我在这里使用的是 11g 语法——如果您使用的是旧版本,则可以使用旧的 SELECT jobID_seq.nextval into :new.jobID from dual 语法)

    SQL> create trigger trg_logs
      2    before insert on logs
      3    for each row
      4  begin
      5    :new.jobID := jobID_seq.nextval;
      6  end;
      7  /
    
    Trigger created.
    
    SQL> create trigger trg_status
      2    before insert on status
      3    for each row
      4  begin
      5    :new.jobID := jobID_seq.currval;
      6  end;
      7  /
    
    Trigger created.
    

    不过,我不太确定尝试像这样自动填充外键是否真的有意义。例如,在某些情况下,您可能会在子表中为您不只是插入的父行添加行。也许您可以通过向status 表上的触发器添加IF 条件来解决此问题,以检查是否已经提供了非NULL 值

    create trigger trg_status
      before insert on status
      for each row
    begin
      if( :new.jobID IS NULL )
      then
        :new.jobID := jobID_seq.currval;
      end if;
    end;
    

    【讨论】:

    • 感谢您的详细回答,我的理解是外键是根据父列中的条目自动填充的,但这没有发生,而且我也找不到在外键中输入值的方法。
    • @Rachel = 默认情况下,不,外键不会自动填充。通常,您必须在执行INSERT 时提供该值。通常,如果您知道要将jobID 用于logs 中最近插入的行,您将明确使用序列的currval
    • 谢谢,你知道如何使用休眠来做到这一点吗?
    • @Rachel - 不是我的头顶。添加了一个 Hibernate 标签,希望我们能吸引到一些 Hibernate 专家。如果您想自动执行此操作,并假设您永远不会在同一会话的早期创建父行的情况下创建子行(这很奇怪但并非不可能),您可以定义我发布的触发器之一,然后插入来自 Hibernate 的 NULL
    • 感谢您的意见,让我试一试,看看是否达到目标,非常感谢!!!
    【解决方案2】:

    在日志表中插入行后,只需使用currval

    insert into logs (jobid) values (seq_jobid.nextval);
    insert into status (jobid) values (seq_jobid.currval);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-14
      • 2012-11-25
      • 1970-01-01
      • 2012-11-20
      相关资源
      最近更新 更多