【问题标题】:SQL - Spooling insertsSQL - 假脱机插入
【发布时间】:2018-12-04 16:31:14
【问题描述】:

我正在创建插入语句来填充我的表。当我测试它们时它们运行良好,然而,当我开始假脱机之前工作的相同代码突然给我一个错误(ORA-00001:违反唯一约束)。在研究该问题时,似乎是在尝试将重复信息输入表时出现问题。但是,我总是在假脱机之前清除序列并重新输入它们,所以这没有意义。这是我正在尝试运行的示例,正​​如我所说的,否则代码可以正常工作:

SQL> INSERT INTO bill_tos_sr
2 (
3 bill_to_no,
4 bill_to_name,
5 bill_to_street,
6 bill_to_city,
7 bill_to_state,
8 bill_to_zip,
9 bill_to_phone  
10 )
11 VALUES
12 (bill_tos_seq.NEXTVAL,
13 'Walmart',
14 '1000 Indiantown St',
15 'Ft Lauderdale',
16 'FL',
17 '33401',
18 '9438476698'
19 );
INSERT INTO bill_tos_sr
*
ERROR at line 1:
ORA-00001: unique constraint (MONPM16.BILL_TO_NO_PK) violated

【问题讨论】:

  • 我不确定这与假脱机有什么关系,或者您在此处如何使用该术语。 “清除序列并重新输入它们”是什么意思 - 将序列重置为从 1 重新开始?您是否同时从表中删除所有先前插入的数据?或者,如果您想保留数据,重新设置序列以使其开始高于现有的最高 PK 值?
  • 假脱机是指打开该功能,以便我的输入和输出保存到 .txt 文件。在打开假脱机功能之前,我测试了代码并成功创建了一行。然后我删除序列以重置它并在打开线轴之前再次创建它。然后我尝试重复该过程,以便将其捕获到 .txt 文件中,然后才给出错误。我只是对为什么代码在我测试它时运行但在启动假脱机文件功能后没有运行感到困惑。
  • OK,但假脱机输出将无效。至关重要的是,你没有提到的是你对第一次插入的数据做了什么——你删除了吗? (也许您希望它被回滚,但事实并非如此——因为您退出 SQL*Plus 时没有显式回滚,默认情况下会提交;或者您发出 DDL 来重置序列,这也会提交。)看起来您插入了一行,重置了序列,并尝试再次插入完全相同的行 - 这意味着您得到的错误是正确的。您必须先删除该行,然后再尝试重新插入。

标签: sql oracle spool insert-statement


【解决方案1】:

重置序列(在这种情况下删除和重新创建)对表中已存在的数据没有影响。除了通过您的代码之外,序列和表之间没有真正的关系。 (例如,您可以在多个表中使用相同的序列)。如果您在 12c+ 中使用标识列,那将是不正确的;但你不在你的例子中。

所以实际上你所做的是:

create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);
drop sequence bill_tos_seq;
create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);

除非您另外指定,否则序列的两个版本都将从 1 开始,这意味着您的两个插入都将尝试创建一个将 bill_to_no 设置为 1 的行 - 这违反了约束。

您需要先从表中删除数据,然后再尝试重新插入。如果一开始是空的,那么您可以进行简单的截断或删除(当然要小心!)。

create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);
drop sequence bill_tos_seq;
truncate table bill_tos_sr;
create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);

如果在您开始之前它已经有一些数据,那么您需要弄清楚您第一次插入了哪些行,然后只删除那些。

您也可以通过回滚测试并重新运行它:

create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);
rollback;
drop sequence bill_tos_seq;
create sequence bill_tos_seq;
insert into bill_tos_sr (bill_to_no, ...) values (bill_tos_seq.nextval, ...);

请注意,如果您这样做,则必须在 之前删除/创建序列,因为 DDL 隐式提交;所以之后的回滚不会有任何效果。

您可能在错误的位置回滚,或者您根本没有回滚并且没有意识到数据已经由于其他原因提交 - 也许您退出 SQL*Plus 并且没有意识到默认情况下也会提交。提交数据后,您必须先将其删除,然后才能重新插入,否则您将继续违反约束。

但是,这与假脱机输出无关。

【讨论】:

    【解决方案2】:

    我假设BILL_TO_NO_PKBILL_TO_NO 列的PK/唯一约束。

    插入时,您将提供来自序列bill_tos_seq.NEXTVAL 的新值。似乎序列已重新启动,或者该数据是手动输入到表中的。

    在任何情况下,序列值都会与表中的现有数据发生冲突。

    解决方案?我会找到列的最大值,然后将序列值设置为比该值大一。

    【讨论】:

      猜你喜欢
      • 2017-04-01
      • 2011-02-03
      • 2013-05-19
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2012-07-30
      • 1970-01-01
      • 2020-07-02
      相关资源
      最近更新 更多