当前位置: 首页 > 知识库问答 >
问题:

是否在PL/SQL中选择启动事务

长孙深
2023-03-14

我被告知下面的代码不能帮助我检查重复,因为在SELECT和UPDATE语句之前,结果可能不同。

PROCEDURE AddNew(Pname VARCHAR2, Pcountry VARCHAR2)
AS
    already_exists BOOLEAN;
BEGIN
    SELECT COUNT(*)>0 INTO already_exists FROM Publishers WHERE name=Pname;
    IF already_exists THEN
        RAISE_APPLICATION_ERROR(-20014,'Publisher already exists!');
    END IF;
    INSERT INTO Publishers(id,name,country)
        VALUES (NewPublisherId(),Pname,Pcountry);
END;

这篇文章声称SELECT启动了一个事务:为什么我在从数据库视图中选择时得到了一个打开的事务?

所以呢?选择是否启动事务?

共有1个答案

郏博瀚
2023-03-14

后者是真的:https://docs.oracle.com/cloud/latest/db112/sqlrf/statements_10005.htm#sqlrf01705

事务隐式地以任何获得TX锁的操作开始:

  • 发出修改数据的语句时
  • 发出SELECT...FOR UPDATE语句时
  • 用SET transaction语句或DBMS_TRANSACTION包显式启动事务
CREATE TABLE Publishers(
    id int,
    name varchar2(100)
);
SQL> Set transaction name 'session 1';

Transaction set.

SQL> select count(*) FROM Publishers where name = 'John';

  COUNT(*)
----------
         0

SQL> INSERT INTO Publishers(id,name) VALUES(1,'John');

1 row created.
SQL> Set transaction name 'session 2';

Transaction set.

SQL> select count(*) FROM Publishers where name = 'John';

  COUNT(*)
----------
         0
SQL>  INSERT INTO Publishers(id,name) VALUES(1,'John');

1 row created.
SQL> Commit;

Commit complete.
SQL> Commit;

Commit complete.
select * from publishers;
        ID NAME                                                                                                
---------- ----------------------------------------------------------------------------------------------------
         1 John                                                                                                
         1 John         

===========编辑==================

可以通过在开始时执行语句集事务隔离级别SERIALIZABLE来避免重复。-@draex_

许多人认为隔离级别可序列化将神奇地解决这个问题。不幸的是,它没有帮助。让我们看看它在一个简单的示例中是如何工作的:会话#1

SQL>  SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Transaction set.

SQL> select count(*) FROM Publishers where name = 'John';

  COUNT(*)
----------
         0

SQL> INSERT INTO Publishers(id,name) VALUES(1,'John');

1 row created.
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Transaction set.

SQL>  select count(*) FROM Publishers where name = 'John';

  COUNT(*)
----------
         0

SQL> INSERT INTO Publishers(id,name) VALUES(1,'John');

1 row created.
SQL> commit;

Commit complete.

SQL> select * from publishers;

        ID  NAME
----------  --------
         1  John
SQL> commit;

Commit complete.

SQL> select * from publishers;
            ID  NAME
    ----------  --------
             1  John
             1  John

正如您所看到的,隔离级别可序列化的魔力没有发挥作用。

 类似资料:
  • 主要内容:开始和结束事务,提交事务,回滚事务,自动事务控制在本章中,我们将讨论和学习PL/SQL中的事务。 数据库事务是由一个或多个相关SQL语句组成的原子工作单元。它被称为原子操作,因为构成事务的SQL语句带来的数据库修改可以共同提交,即永久化到数据库或从数据库回滚(撤销)。 成功执行的SQL语句和提交的事务不一样。即使成功执行SQL语句,除非提交包含语句的事务,否则可以回滚该语句,并且可以撤消语句所做的所有更改。 开始和结束事务 事务有开始和结束。当

  • 问题内容: 我在Sql Server 2008上有这样的查询: 在上面看到的选择查询中,SqlServer是否优化查询以免一次又一次地计算DATEADD结果。还是将DATEADD结果存储在临时变量中是我自己的责任吗? 问题答案: 令人惊讶的是,我发现内联使用GETDATE()似乎比预先执行这种类型的计算更有效。 如果您检查这些计划,则中间查询将始终以最低的成本(但并非总是最低的花费时间)出现。当然

  • 启动开发环境服务可以设置不同的 hostname,你可以在启动命令后面加上--hostname 主机名 或 -H 主机名。它将会启动一个 TCP 服务器来监听连接所提供的主机。

  • 第一种方法: SetRebootFlag true IfRebootFlag 0 +2 同时如果有!define MUI_FINISHPAGE_NOREBOOTSUPPORT 记得删掉 第二种方法: 可以跳出窗口询问 MessageBox MB_YESNO|MB_ICONQUESTION|MB_TOPMOST "请重启以便补丁安装完全及垃圾清理完整!" IDNO +2 Reboot

  • Presto SQL真的缺少SELECT语句中的TOP X功能吗? 如果有,在此期间是否有变通办法? https://prestodb.io/

  • 本文向大家介绍检查数字是否为PL / SQL中的回文,包括了检查数字是否为PL / SQL中的回文的使用技巧和注意事项,需要的朋友参考一下 在本节中,我们将看到如何检查号码是否是回文或者是不使用PL / SQL。在PL / SQL代码,一些命令组被布置语句的相关声明的一个块中。 如果数字与该数字相反,则该数字为回文。假设一个数12321,这是回文,但12345是不是回文。 示例 输出结果