【问题标题】:how to enforce uniqueness of non-unique key in Oracle table for each task如何为每个任务强制 Oracle 表中非唯一键的唯一性
【发布时间】:2016-12-08 01:44:26
【问题描述】:

标题可能有点混乱 - 我将在这里深入探讨细节......

想象一下简化的日志表:

run_id  |  step_id  |  result |
--------------------------------
   1    |     1     |  done   |
   1    |     2     |  done   |
   1    |     3     |  done   |
   1    |     4     |  done   |
   2    |     1     | failed  |
   3    |     1     |  done   |
   3    |     2     |  done   |

但是当我同时运行两个作业(run_id 1 和 2)时,碰巧他们共享了不正确的 run_id !!

我希望每个工作都有单独的 id .. 显然 :)

如何在 Oracle(PL/SQL - 主要是包)中对同时开始的作业(即早上 6 点)强制执行它...

你有什么想法吗?你如何解决这种情况?如果我在 (run_id, step_id) 上创建唯一索引怎么办? “第二个”工作会失败吗?还是会自动增加值?

SELECT nvl(max(run_id), 0)+1 INTO v_run_id
FROM my_schema.log_table;

这是代码,获取新值...但它不起作用,因为...如上所述

谢谢

编辑: 作为一种解决方法,我考虑使用字符串和日期...使用 start_date 和常量字符串(run_name 而不是 run_id)...所以表格看起来像

run_name  |      run_date         | step_id  |  result |
--------------------------------------------------------
 my_job#1 |  1/1/2016 7:00:00 AM  |   1      |  done   |
 my_job#1 |  1/1/2016 7:00:00 AM  |   2      |  done   |
 my_job#1 |  1/1/2016 7:00:00 AM  |   3      |  done   |
 my_job#1 |  1/1/2016 7:00:00 AM  |   4      |  done   |
 my_job#2 |  1/1/2016 7:00:00 AM  |   1      | failed  |
 my_job#1 |  1/2/2016 7:00:00 AM  |   1      |  done   |
 my_job#1 |  1/2/2016 7:00:00 AM  |   2      |  done   |

这可以工作..我只是好奇如何使用 ID 来做到这一点

【问题讨论】:

    标签: oracle


    【解决方案1】:

    您目前正在获取这样的 run_id:

    SELECT nvl(max(run_id), 0)+1 INTO v_run_id
    FROM my_schema.log_table;
    

    我假设您的代码在插入每个步骤时使用run_id。你应该像这样创建一个序列:

    CREATE SEQUENCE run_id_seq;
    

    然后将上面的查询替换为:

    SELECT run_id_seq.nextval FROM dual;
    

    如果您的表中已有数据,则在创建序列时可能需要START WITH 一个值,以确保它不会发生冲突。

    【讨论】:

      【解决方案2】:

      处理这个问题的更好方法是使用序列。在 Oracle 12c 中,您可以使用 generated always 构造自动为列分配顺序值(如其他数据库中的 identityserialauto_increment)。

      在旧版本中,您使用触发器来维护它。在表中定义一列和一个序列后,触发代码如下:

      create trigger t_trigger
      before insert on t
      for each row
      begin
          select seq.nextval into new.id
          from dual;
      end;
      

      使用这样的构造,值永远不会相同。

      【讨论】:

      • 但这意味着我每次插入都会得到不同的 run_id 对吗?我将无法通过 run_id 识别相同的“运行”
      • @Mr.P 是的,你会的。因此,在您的情况下,您需要直接从序列中获取值,而不是为插入的每一行使用触发器。
      猜你喜欢
      • 2021-01-01
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      • 2014-06-20
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多