gpt4 book ai didi

sql - 多次插入SQL oracle

转载 作者:行者123 更新时间:2023-12-02 02:11:08 25 4
gpt4 key购买 nike

当您有标识列时,如何在 Oracle 12c 中使用 SQL 进行多次插入?

INSERT ALL
INTO Table1 (Column2) Values (1)
INTO Table1 (Column2) Values (2)
SELECT * FROM dual;

其中 Table1 将 column1 作为标识,会将标识列设置为具有相同的值,这违反了主键约束。

CREATE TABLE Table1 (
Table1Id NUMBER GENERATED ALWAYS AS IDENTITY,
column2 VARCHAR2(255),
column3 NUMBER,
PRIMARY KEY (Table1Id)
);

INSERT ALL
INTO Table1 (column2, column3) VALUES ('a', '1')
INTO Table1 (column2, column3) VALUES ('b', '2')
SELECT * FROM dual;

--SQL Error: ORA-00001: unique constraint violated

我做错了什么?

最佳答案

编辑添加了两个测试用例和一个可能的解决方法。

虽然Insert语句和insert all语句实际上是相同的传统插入语句。但当涉及到序列时,它们的工作方式有所不同。

测试用例 1:标识列

SQL> DROP TABLE table1 PURGE;

Table dropped.

SQL>
SQL> CREATE TABLE Table1 (
2 Table1Id NUMBER GENERATED ALWAYS AS IDENTITY,
3 column3 NUMBER,
4 PRIMARY KEY (Table1Id)
5 );

Table created.

SQL>
SQL> INSERT ALL
2 INTO Table1 (column3) VALUES ('1')
3 INTO Table1 (column3) VALUES ('2')
4 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.SYS_C0010439) violated


SQL>

让我们看看幕后到底发生了什么 -

SQL> CREATE TABLE Table1 (
2 Table1Id NUMBER GENERATED ALWAYS AS IDENTITY,
3 column3 NUMBER,
4 CONSTRAINT A UNIQUE (Table1Id)
5 );

Table created.

SQL> INSERT ALL
2 INTO Table1 (column3) VALUES (1)
3 INTO Table1 (column3) VALUES (2)
4 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.A) violated


SQL> SELECT * FROM table1;

no rows selected

SQL> ALTER TABLE table1
2 DISABLE CONSTRAINT a;

Table altered.

SQL> INSERT ALL
2 INTO Table1 (column3) VALUES (1)
3 INTO Table1 (column3) VALUES (2)
4 SELECT * FROM dual;

2 rows created.

SQL> SELECT * FROM table1;

TABLE1ID COLUMN3
---------- ----------
2 1
2 2

SQL>

因此,序列进行到 nextval,但是我们第一次执行“全部插入”时存在唯一约束违规。接下来,我们禁用唯一约束,随后的“插入全部”显示序列没有进展到 nextval,而是尝试插入重复键

尽管 INSERT-INTO-SELECT 语句不会出现此问题。

SQL> INSERT INTO table1(column3) SELECT LEVEL FROM dual CONNECT BY LEVEL <=5;

5 rows created.

SQL>
SQL> SELECT * FROM table1;

TABLE1ID COLUMN3
---------- ----------
2 1
3 2
4 3
5 4
6 5

SQL>

令人惊讶的是,根据元数据,序列应该自动进入 nextval,但使用 Insert All 语句时不会发生这种情况。

SQL> SELECT COLUMN_NAME,
2 IDENTITY_COLUMN,
3 DATA_DEFAULT
4 FROM user_tab_cols
5 WHERE table_name ='TABLE1'
6 AND IDENTITY_COLUMN='YES';

COLUMN_NAME IDENTITY_COLUMN DATA_DEFAULT
--------------- --------------- ------------------------------
TABLE1ID YES "LALIT"."ISEQ$$_94458".nextval

SQL>

测试用例 2:显式使用序列

无论使用标识列还是使用显式序列INSERT ALL 的工作方式都是相同的。

SQL> DROP SEQUENCE s;

Sequence dropped.

SQL>
SQL> CREATE SEQUENCE s;

Sequence created.

SQL>
SQL> DROP TABLE t PURGE;

Table dropped.

SQL>
SQL> CREATE TABLE t (
2 ID NUMBER,
3 text VARCHAR2(50),
4 CONSTRAINT id_pk PRIMARY KEY (ID)
5 );

Table created.

SQL>
SQL> INSERT ALL
2 INTO t VALUES (s.nextval, 'a')
3 INTO t VALUES (s.nextval, 'b')
4 INTO t VALUES (s.nextval, 'c')
5 INTO t VALUES (s.nextval, 'd')
6 SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.ID_PK) violated


SQL>
SQL> SELECT * FROM T;

no rows selected

SQL>
SQL> ALTER TABLE t
2 DISABLE CONSTRAINT id_pk;

Table altered.

SQL> INSERT ALL
2 INTO t VALUES (s.nextval, 'a')
3 INTO t VALUES (s.nextval, 'b')
4 INTO t VALUES (s.nextval, 'c')
5 INTO t VALUES (s.nextval, 'd')
6 SELECT * FROM dual;

4 rows created.

SQL> SELECT * FROM T;

ID TEXT
---------- ----------------------------------------
2 a
2 b
2 c
2 d

SQL>

可能的解决方法 - 使用 ROW LEVEL 触发器

SQL> CREATE OR REPLACE TRIGGER t_trg
2 BEFORE INSERT ON t
3 FOR EACH ROW
4 WHEN (new.id IS NULL)
5 BEGIN
6 SELECT s.NEXTVAL
7 INTO :new.id
8 FROM dual;
9 END;
10 /

Trigger created.

SQL> truncate table t;

Table truncated.

SQL> INSERT ALL
2 INTO t (text) VALUES ('a')
3 INTO t (text) VALUES ('b')
4 INTO t (text) VALUES ('c')
5 INTO t (text) VALUES ('d')
6 SELECT * FROM dual;

4 rows created.

SQL> SELECT * FROM t;

ID TEXT
---------- -------------------------
3 a
4 b
5 c
6 d

SQL>

关于sql - 多次插入SQL oracle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28523262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com