但是当在匿名 PL/SQL 块中执行时,它会永远挂起:
我猜两件事:
- 您的表 (Existing_Table) 对您在插入语句中使用的列之一具有约束。
- 您忘记在执行 SQL 语句和 PL/SQL 匿名块之间发出提交。
在 SQL 和 PL/SQL 中执行您的语句在性能上应该没有差异。它应该在几乎相同的时间内执行。
但是由于 Constraint 或 Commit,它被阻塞了,因为行被锁定了。
这是一个例子。
在会话 1 中,创建两个表。一个有约束,一个没有:
create table Existing_Table
(
existing_column number primary key
);
create table Existing_Table_2
(
existing_column number
);
在同一会话中,执行以下 SQL 语句:
insert into Existing_Table (existing_column) values (1);
结果:
1 row inserted.
在另一个(会话 2)上,执行以下 PL/SQL 匿名块:
begin
insert into Existing_Table (existing_column) values (1);
end;
这将一直挂起,直到您在 Session 1 中发出提交。
这是因为会话 1 为现有列“保留”了“1”的值,并且在您发出提交时将被“保存”。
会话 2 只是在等待会话 1 提交或回滚插入。
现在,当我返回会话 1 并发出提交时,该行将被解锁。
但是,由于违反完整性约束,会话 2 将导致错误:
Error starting at line : 1 in command -
begin
insert into Existing_Table (existing_column) values (1);
end;
Error report -
ORA-00001: unique constraint (APPS.SYS_C001730810) violated
ORA-06512: at line 2
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
现在,另一个没有约束的表示例。
在没有提交的情况下在会话 3 中运行以下 SQL:
insert into Existing_Table_2 (existing_column) values (1);
结果:
1 row inserted.
在会话 4 的匿名 PL/SQL 块内运行相同的 SQL:
begin
insert into Existing_Table_2 (existing_column) values (1);
end;
结果:
PL/SQL procedure successfully completed.
即使在会话 1 中没有提交,它也可以正常插入,因为没有违反任何约束。
请注意,在您发出提交之前,会话 3 和 4 中的任何数据都不会实际保存在数据库中。
在此处查看有关会话阻止的其他文章:
Tracking Oracle blocking sessions
Find blocking sessions