【问题标题】:ORA 000001 Unique constraint violatedORA 000001 违反唯一约束
【发布时间】:2012-07-11 16:15:51
【问题描述】:

我有一个插入到具有 dep_id 和 emp_id 主键的表的语句。我的 java 程序为新记录生成一个新的 emp_id 并插入它。例如,如果我有 dep_id = 100 和 emp_id = 25,我无法插入 dep_id = 100 和 emp_id = 26 的记录,但我可以插入 dep_id = 100 和 emp_id = 27 的记录。我通过检查如果存在某种组合(dep_id = 100 和 emp_id = 26),则选择语句。没有那种东西。我还是做了一个 DELETE from where dep_id = 100 and emp_id = 26 and Commit 只是为了确定,然后尝试插入,但它仍然不起作用。可能有什么问题?以下是代码:修改后的 DDL 和 Insert 语句(从 Eclipse 控制台获取)

                                                                                    CREATE  TABLE "TestDB"."table1" 
 (  "dep_id" NUMBER(20,0), 
"emp_id" NUMBER(20,0), 
"STATUS" VARCHAR2(10 BYTE), 
"PRO_LEVEL" VARCHAR2(14 BYTE), 
"new_sql_stmt" VARCHAR2(4000 BYTE), 
"DEL_TEM" VARCHAR2(500 BYTE), 
"tab_name" VARCHAR2(4000 BYTE), 
"COL_NAME" VARCHAR2(4000 BYTE), 
"QUERY_TYPE" VARCHAR2(4000 BYTE), 
"NAME" VARCHAR2(4000 BYTE), 
"DT_MODIFIED" DATE DEFAULT SYSDATE

)

  CREATE UNIQUE INDEX "TestDB"."table1_PK" ON "TestDB"."table1" ("dep_id", "emp_id") 


     INSERT into table1            (dep_id,emp_id,status,new_sql_stmt,tab_name,col_name,query_type,NAME)values('100','26','Unlock','INSERT into testTab(id_some,nm_some,id_some_origin,flag,some_code,author,order) values  (''S11111111'',''trialSome00'','''',''y'','''',''100'',0)','testTab','nm_some','INSERT','trialSome00')

请注意,插入语句本身有另一个插入语句作为值。这个插入语句(主要的)在应用程序的许多其他地方使用。另外,我使用 100 的 dep_id 是一个测试 dep_id。除了我没有人使用它。

【问题讨论】:

  • 你确定你的java代码是同步的吗?它可能被多个线程调用。
  • 它是一个没有任何线程的简单应用
  • 你所描述的没有意义。您可能遗漏了某些部分(即另一个会话,可能运行不同的应用程序,正在插入并提交带有dep_id=100emp_id=26 的行)或者您的描述不正确。您能否发布 DDL 以创建表并发布一些示例代码,我们可以在我们的机器上运行以复制问题?
  • @Raghu - 你知道max(emp_id) + 1 不会在多用户环境中工作,对吧?同时运行的两个会话将看到相同的max(emp_id),并将尝试插入具有相同emp_id 值的行,从而导致您描述的错误。您是否有理由不使用序列来生成密钥?
  • Nouuu,让我们去吃choppa吧! Ñññaaggghhhhh... 多用户 + 选择最大值 = 你不想活了。如果你想活下去,跟我来使用sequence/auto_increment :)

标签: java oracle insert ora-00001 batch-updates


【解决方案1】:

创建一个 Oracle 序列:

CREATE SEQUENCE emp_id_seq MINVALUE 1 START WITH 1 INCREMENT BY 1; 

现在您可以在代码中对该序列调用“nextval”方法(这可以使用 JDBC 或几乎每个 ORM 来完成,如果不是全部的话),或者您可以在该列上放置一个自动获取的触发器序列中的 nextval 并在您执行插入操作时将其插入表中(在 oracle 上的 IIRC,您将在触发器中使用“BEFORE INSERT”运算符)。

例如

create or replace trigger mytable_emp_id_trigger
before insert on mytable
for each row
begin
    select emp_id_seq.nextval into :emp.id from dual;
end;
/

这样做是线程安全的,你永远不会看到这样的冲突发生。

如果您坚持在 java 代码中执行此操作(假设 DBA 不允许您创建另一个序列,但是为什么——如果他们不这样做我会感到惊讶),那么您将不得不这样做方法线程安全。可能最好使用同步方法创建单例(您可以创建单例 EJB)来提供下一个值。您从该单例类中获取您的 id,而不是任何其他类或 ejb 以避免像您现在遇到的问题(无论当前问题是否是因为这个,您现在遇到的是典型的多线程与非同步冲突多线程环境中的方法)。

与此同时,如果您真的想了解正在发生的事情,请使用您的调试器并观察您的变量以查看现有代码正在生成什么。调试器和手表是你的朋友。你最好的朋友。

【讨论】:

  • 感谢 BillR 和今天所有试图帮助我的人。虽然我仍然不知道是什么导致了这个问题,但我也在考虑必须改变获取下一个值的方式。我会同意的。
猜你喜欢
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多