【问题标题】:00001. 00000 - "unique constraint (%s.%s) violated"00001. 00000 - “违反了唯一约束 (%s.%s)”
【发布时间】:2014-03-06 12:04:31
【问题描述】:

我有 MAIN_TABLE,其中包含 700 万条记录。我必须

  1. 在 MAIN_TABLE 中保留最近 3 个月的数据
  2. 在 MAIN_TABLE_ARCHIVAL 中归档过去 4 到 12 个月的数据
  3. 清除所有超过 12 个月的数据

我创建了一个带有游标的存储过程,以便从 MAIN_TABLE 复制到 MAIN_TABLE_ARCHIVAL。 我有复合主键(CONSTRAINT "PK_MAIN_TABLE" PRIMARY KEY ("SERVICE", "TR_SOURCE", "TR_ID")

复制时我得到 00001. 00000 - “违反唯一约束 (%s.%s)”错误,即使我没有插入任何重复键但同时记录被复制到 MAIN_TABLE_ARCHIVE。

我的代码看起来像(我有大约 20 个字段,所以我没有粘贴整个代码):

DECLARE
   c_id customers.id%type;
   c_name customers.name%type;
   c_addr customers.address%type;

   CURSOR c_customers is
    SELECT id, name, address FROM customers;
BEGIN
  OPEN c_customers;
  LOOP
    FETCH c_customers into c_id, c_name, c_addr;
    EXIT WHEN c_customers%notfound;
    dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
    commit;
  END LOOP;
  CLOSE c_customers;
END;
/

我尝试调试,但没有运气,因为我是 PL/SQL 新手。谁能告诉我为什么会这样?我应该如何执行上述任务?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    要将数据从一个表复制到另一个表,您不需要任何游标。你甚至不需要存储过程。你可以用一个简单的 sql 语句来实现:

    insert into MAIN_TABLE_ARCHIVAL select * from MAIN_TABLE where <...your condition...>
    

    为了提高性能,您可以使用“+append”提示。

    【讨论】:

    • 你确定吗?即使对于带有日志记录追加的表,也会将数据放到新的范围内,并且有时比通常的插入要快得多。
    • 最有效的任务解决方案是使用分区。如果两个表都按月分区,则可以通过交换分区来将数据从一个表移动到另一个表(这不包括任何数据移动)。但我认为这样的解决方案对于新手来说太复杂了。
    • MAIN_TABLE 包含大约 800 万条记录。如果我们使用简单的 insert into --select * from -- 语句会不会有任何性能问题。我在某处读到有关批量复制会提高性能的信息。我们也可以实现所有三个 1)在 MAIN_TABLE 中保留最近 3 个月的数据 2)在 MAIN_TABLE_ARCHIVAL 中归档最近 4 到 12 个月的数据 3)通过在上述语句中添加一些条件来清除所有超过 12 个月的数据??
    【解决方案2】:

    看看这个: Unique constraint violation during insert: why? (Oracle)

    将序列中的起始值与表中的 MAX(ID) 进行比较。

    SELECT MAX(ID_Column) FROM Schema.Table; SELECT Schema.Table_Sequence.nextval from DUAL;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多