触发错误时回滚事务

2024-02-25

我正在尝试检查要插入系统的房间在该日期是否已出租。我已经考虑过计算与房间号和日期匹配的行,然后回滚事务。但即使我更改了代码以引发用户定义的异常,我仍收到以下错误:

ERROR:  cannot begin/end transactions in PL/pgSQL
HINT: Use a BEGIN block with an EXCEPTION clause instead.
CONTEXT: PL/pgSQL function "checkRoom"() line 17 at SQL statement
CREATE OR REPLACE FUNCTION "checkRoom"() RETURNS TRIGGER AS
$BODY$
DECLARE 
    counter integer;
  BEGIN
    SELECT COUNT("num_sesion")
    FROM "Sesion"
    INTO counter
    WHERE "Room_Name"=NEW."Room_Name" AND "Date"=NEW."Date";

    IF (counter> 0) THEN -- Probably counter>1 as it's triggered after the transaction..
        raise notice 'THERE'S A ROOM ALREADY!!';
        raise exception 'The room is rented at that date';
    END IF;
    RETURN new;
EXCEPTION
    WHEN raise_exception THEN
        ROLLBACK TRANSACTION;
        RETURN new;
END;$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;

然后我创建触发器:

CREATE TRIGGER "roomOcupied" AFTER INSERT OR UPDATE OF "Room_Name", "Date"
ON "Sesion" FOR EACH ROW
EXECUTE PROCEDURE "checkRoom"();

距离我上次接触 SQL 已经过去了 2 年,plsql 和 plpgsql 之间的变化让我抓狂。


触发函数存在几个问题:

  • Use IF EXISTS (...) THEN https://stackoverflow.com/questions/11892233/pl-pgsql-checking-if-a-row-exists-select-into-boolean/11892796#11892796而不是计算所有出现的次数。更快、更简单。看:

    • PL/pgSQL 检查行是否存在 https://stackoverflow.com/questions/11892233/pl-pgsql-checking-if-a-row-exists/11892796#11892796
  • 有触发功能AFTER INSERT OR UPDATE可以直接返回NULL. RETURN NEW仅与名为的触发器相关BEFORE. 手册 https://www.postgresql.org/docs/current/trigger-definition.html:

    对于操作后触发的行级触发器,返回值将被忽略,因此它们可以返回NULL.

  • 单引号不平衡。

  • As @Pavel 解释道 https://stackoverflow.com/a/16700934/939860,您无法从 plpgsql 函数内控制事务。任何未处理的异常都会迫使您的整个事务自动回滚。所以,只需删除EXCEPTION block.

你的假设触发器被重写:

CREATE OR REPLACE FUNCTION check_room()
  RETURNS TRIGGER AS
$func$
BEGIN
   IF EXISTS (
         SELECT FROM "Sesion"    -- are you sure it's not "Session"?
         WHERE  "Room_Name" = NEW."Room_Name"
         AND    "Date" = NEW."Date") THEN
     RAISE EXCEPTION 'The room is rented at that date';
   END IF;
   RETURN NULL;
END
$func$  LANGUAGE plpgsql;

A BEFORE触发更有意义。

But a UNIQUE INDEX ON ("Room_Name", "Date")也会做同样的事情,而且效率更高。然后,任何违反的行都会引发重复键异常并回滚事务(除非捕获并处理)。在现代 Postgres 中,你可以选择跳过或转移这样的INSERT尝试与INSERT ... ON CONFLICT .... See:

  • 如何在 PostgreSQL 中进行 UPSERT(合并、插入...重复更新)? https://stackoverflow.com/questions/17267417/how-to-upsert-merge-insert-on-duplicate-update-in-postgresql/17267423#17267423

高级用法:

  • 如何在 PostgreSQL 中使用 RETURNING 和 ON CONFLICT? https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/42217872#42217872
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

触发错误时回滚事务 的相关文章

  • MySQL NOT IN 来自同一个表中的另一列

    我想运行 mysql 查询来选择表中的所有行films其中的值title该列不存在于另一列的所有值中的任何位置 collection 这是我的表格的简化版本 其中包含内容 mysql gt select from films id titl
  • 如何将今天的日期返回到 Oracle 中的变量

    我想做这个 DECLARE today as smalldatetime SELECT today GetDate 但我需要一个oracle翻译 甲骨文使用SYSDATE 还有 ANSI 标准CURRENT TIMESTAMP 除其他外 S
  • 如何在 SQL Server 2012 中选择除一列之外的所有列? [复制]

    这个问题在这里已经有答案了 有没有一种方法可以选择所有列 但只选择我不想选择的特定列 我的意思是有时我会遇到这样的问题 表有数百个字段 而我只需要删除一个字段 我需要重写所有列吗 有什么窍门吗 喜欢select
  • CONTAINS 不适用于 Oracle Text

    我在执行此查询时遇到问题 SELECT FROM gob attachment WHERE CONTAINS gob a document java gt 0 它给了我 ORA 29902 error in executing ODCIIn
  • 如何使用 SQL 查询创建逗号分隔的列表?

    我有 3 个表 名为 应用程序 ID 名称 资源 id 名称 应用程序资源 id app id resource id 我想在 GUI 上显示所有资源名称的表格 在每一行的一个单元格中 我想列出该资源的所有应用程序 以逗号分隔 所以问题是
  • 根据数据框中的内容从SQL Server删除行

    我在 SQL Server 中有一个名为的库存表dbo inventory其中包含Year Month Material and Stock quantity 我每天都会收到 csv 文件形式的新库存计数 需要将其加载到dbo invent
  • 如何将 SQL Server 中同一表中的一列插入到另一列中

    我需要将一列的数据插入到同一个表中的另一列中 谁能告诉我这个怎么写 Thanks UPDATE table SET col 2 col 1
  • 仅选择 Varchar 列中的数字[重复]

    这个问题在这里已经有答案了 在 SQL Server 2008 R2 中 我在 varchar 12 列中有一些数据 它看起来像这样 Data 1234 1765 34566 123 SDRMH HJG434 我想从所有包含 的行中删除 并
  • Rails 中 WHERE 子句中的 ALL 运算符

    关联关系如下图所示 InstructorStudent has many fees Fee belongs to instructor student 我想要获得在所有给定数组中具有每月详细信息的指导学生 如果其中任何一个中不存在每月详细信
  • 重建数据库中的所有索引

    我有一个非常大的 SQL Server 2008 R2 数据库 1 5TB 并将在同一个表中的列之间复制一些数据 我被告知该架构有大量索引 并且想知道是否有默认查询或脚本可以重建所有索引 是否也被建议同时更新统计数据 30 个表中的每一个都
  • 一张表中按最大日期过滤重复行的 SQL 查询

    我有一个 SQL 数据库 persons 它具有基于 IDNum 列的重复条目 我需要查询条目并仅根据最新创建日期显示行或重复条目 这是查询 SELECT IDNum PersonPGUID CreatedDateTime FirstNam
  • mysql 详细查询字符串,如通配符

    不知道如何标题我的问题 哈哈 下面是我需要的 我的数据库中的值如下所示 test example 1 test example 2 test example TD 1 这些值的长度可以不同 test example 只是一个示例 某些值将具
  • SQL中如何识别字符串的第一个字符是数字还是字符

    我需要将数据中的第一个字符识别为 SQL Server 中的数字或字符 我对此比较陌生 我不知道从哪里开始 但这是我到目前为止所做的事情 我的数据看起来像这样 TypeDep Transfer From 4Z2 Transfer From
  • 如何检查一个值是否已经存在以避免重复?

    我有一个 URL 表 但我不想要任何重复的 URL 如何使用 PHP MySQL 检查给定 URL 是否已在表中 如果您不想重复 可以执行以下操作 添加唯一性约束 use REPLACE http dev mysql com doc ref
  • postgresql中的按日期聚合函数分组

    我在运行此查询时遇到错误 SELECT date updated at count updated at as total count FROM persons WHERE persons updated at BETWEEN 2012 1
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • 如何避免连接两个表时重复

    Student Table SID Name 1 A 2 B 3 C Marks Table id mark subject 1 50 physics 2 40 biology 1 50 chemistry 3 30 mathematics
  • MySQL 正在将我的时间戳值转换为 0000-00-00

    我是 PHP 新手 目前仍在学习中 我认为我的注册表有问题 username password email全部成功插入MySQL registered and last seen不要 我以为我正在使用getTimestamp 错了 但它呼应
  • Oracle SQL-根据记录的日期与历史记录标记记录

    这是我在论坛上的第一篇文章 通常我能够找到我需要的东西 但说实话 我不太确定如何针对该问题提出正确的问题 因此 如果论坛上已经有答案而我错过了 请接受我的歉意 我通过 Benthic Software 在 Oracle 数据库中运行以下代码
  • 使用“AND”表达式构建动态 SQL,而不混淆嵌套条件?

    总的来说 我对 php 和编码相当陌生 我有一系列条件需要测试它们是否已设置 它们是 option1 option2 option3 if isset option1 if isset option2 if isset option3 qu

随机推荐