在 Firebird 的服务器端使用生成器值时,如何不浪费它们?

2023-12-05

检查这段简单的代码,它使用生成器在 Firebird 表中创建唯一的主键:

CREATE OR ALTER TRIGGER ON_BEFOREINSERT_PK_BOOKING_ITEM FOR BOOKING_ITEM BEFORE INSERT POSITION 0
  AS
  BEGIN
    IF ((NEW.booking_item_id IS NULL) OR (NEW.booking_item_id = 0)) THEN BEGIN
      SELECT GEN_ID(LastIdBookingItem, 1) FROM RDB$DATABASE INTO :NEW.booking_item_id;
    END
  END!

该触发器抓取并递增,然后为预订项目 id 分配生成的值,从而为 BOOKING_ITEM 表创建一个自动递增的键。触发器甚至会检查预订 ID 是否尚未分配值。

问题是,如果由于某种原因无法发布 BOOKING_ITEM 记录,自动递增的值将会丢失(浪费)。

关于如何避免这种浪费,我有几个想法,但对每一个都感到担忧。他们来了:

  1. 如果发生过帐错误则递减计数器。在触发器中,我设置了一个 try- except 块(Firebird PSQL 中是否存在 try- except 块?)并运行SELECT GEN_ID(LastIdBookingItem, -1) FROM RDB$DATABASE关于帖子异常。这行得通吗?如果另一笔交易潜入并在我递减生成器之前递增生成器怎么办?那真的会把事情搞砸的。

  2. 使用临时 ID。将 id 设置为某个唯一的临时值,我将其更改为插入后触发器上所需的生成器值。这种方法感觉有点做作,需要一种确保临时 ID 唯一的方法。但是,如果 booking_item_id 是在客户端提供的,我如何将其与临时 id 区分开来呢?另外我需要另一个触发器

  3. 使用事务控制。这类似于选项 1。除了不使用 try-except 块来重置生成器之外,我启动一个事务,然后在记录无法发布时回滚它。我不知道使用事务控制的语法。我想我在某处读到 PSQL 中不允许 SAVEPOINT/SET TRANSACTION 。另外,回滚必须在 AFTER INSERT 触发器中发生,所以我再次需要另一个触发器。

对于任何想要使用生成器的 Firebird 开发人员来说,这无疑是一个问题。还有其他想法吗?我有什么遗漏的吗?


序列不受事务控制,干预它们以获得“无间隙”数字只会引起麻烦,因为另一个事务也可以同时增加序列,导致间隙+重复而不是没有间隙:

  • 开始:生成器值 = 1
  • T1:增量:值为2
  • T2:增量:值为3
  • T1:“回滚”,递减:值为 2(而不是您期望的 1)
  • T3:增量:值为 3 => 重复值

序列主要用于生成人工主键,并且您不应该关心间隙的存在:只要数字唯一标识记录即可。

如果您需要可审计的数字序列,并且要求没有间隙,那么您不应该使用数据库序列来生成它。您可以在创建并提交发票本身后使用序列来分配编号(以便确保它被持久化)。没有编号的发票还不是最终的。然而,即使在这里,也存在出现间隙的机会,例如,如果在分配发票编号和提交之间发生错误或其他失败。

另一种方法可能是明确创建带有间隙编号的零发票(标记为已取消/编号丢失),以便审核员知道该发票发生了什么。

根据当地法律和法规,您不应“重复使用”或回收丢失的号码,因为这可能会被视为欺诈。

您可能会发现其他想法“一系列可审计的数字”。其中还包含一个使用 IBObjects 的 Delphi 项目,但文档本身很好地描述了问题和可能的解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Firebird 的服务器端使用生成器值时,如何不浪费它们? 的相关文章

  • 在 PL/SQL 中将绑定变量与动态 SELECT INTO 子句结合使用

    我有一个关于 PL SQL 中的动态 SQL 语句中可以使用绑定变量的问题 例如 我知道这是有效的 CREATE OR REPLACE FUNCTION get num of employees p loc VARCHAR2 p job V
  • SQL 错误:“没有这样的表”

    我试图解决为什么我的代码为所有查询返回 null 的原因 最后发现 sql 查询什么也没有返回 我使用简约代码创建了一个新的 AIR 文档 s WindowedApplication
  • MySQL 和 Hibernate 之间的主键自增由谁负责?

    MySQL CREATE TABLE role id role INT 11 unsigned NOT NULL AUTO INCREMENT PRIMARY KEY id role AUTO INCREMENT 1 休眠 Entity p
  • 如何查找当前数据库类型

    我们有一个 SQL 脚本可以在多种类型的数据库上执行 是否可以获取正在执行 SQL 脚本的当前数据库的类型 注意 我们不能使用非标准 SQL 即 TSQL 等 不 ANSI SQL 中没有任何关于确定数据库供应商的内容
  • MySql 5.7 ORDER BY 子句不在 GROUP BY 子句中并且包含非聚合列

    我试图在不禁用 my ini 中的 only full group by 的情况下弄清楚 这是我的查询 SELECT p title COUNT t qty AS total FROM payments t LEFT JOIN produc
  • 将 .MDF SQL Server 数据库与 ASP.NET 结合使用与使用 SQL Server

    我目前正在 ASP NET MVC 中编写一个网站 我的数据库 其中还没有任何数据 只有正确的表 使用 SQL Server 2008 我已将其安装在我的开发计算机上 我使用服务器资源管理器从应用程序连接到数据库 然后使用 LINQ to
  • 串行类型的外键 - 确保始终手动填充

    我有两个表 国家和地区 CREATE TABLE Countries id SERIAL name VARCHAR 40 NOT NULL PRIMARY KEY id CREATE TABLE Regions id SERIAL coun
  • SQL:如何在按部分分组的查询中使用子查询?

    如何在按部分分组的查询中使用子查询 我使用 SQL Server 2008 R2 和 Delphi 2010 我收到此错误 Cannot perform an aggregate function on an expression cont
  • Oracle:如何获取刚刚插入的行的序列号?

    如何获取刚刚插入的行的序列号 插入 返回 declare s2 number begin insert into seqtest2 x values aaa returning seq into s2 dbms output put lin
  • 加密数据库字段的好方法?

    我被要求加密数据库中的各种数据库字段 问题是这些字段在读取后需要解密 我在用着Django and SQL Server 2005 有什么好主意吗 See 在 SQL Server 2005 数据库中使用对称加密 https web arc
  • 如何在 SEQUELIZE (nodeJS) 中创建触发器?

    我正在尝试使用sequelize 创建一个触发器 主要思想是创建一个实例CONFIG创建后USER USER MODEL module exports function sequelize DataTypes var User sequel
  • st_intersects 与 st_overlaps

    这两个查询有什么区别 select a gid sum length b the geom from polygons as a roads as b where st intersects a the geom b the geom gr
  • 如何通过 SQL 表关联 SQL 中的实体

    我是数据库设计的初学者 我需要为项目创建数据库 我可以用面向对象的术语解释我想要做什么 值得庆幸的是 数据库专家会很友善地向我解释如何在数据库方面处理这个问题 我想创建一个与位置实体 州 城市 有关系的用户 ID 名称 实体 所以在编程语言
  • 删除数据库中的行后如何重新排序ID

    我正在使用 C 来制作具有 sql 数据库的程序 在数据库中我有一个名为Workers 它有一个自动增量和主键ID column 当我删除一条记录时 ID 之间会出现间隙 删除记录后如何重新排序 ID UPDATE 我要做的就是找到记录后将
  • 从 Getdate() 获取时间

    我想采取Getdate 结果 例如 2011 10 05 11 26 55 000 into 11 26 55 AM 我看过其他地方并发现 Select RIGHT CONVERT VARCHAR GETDATE 100 7 这给了我 11
  • MYSQL从每个类别中随机选择一条记录

    我有一个数据库Items表看起来像这样 id name category int 有几十万条记录 每个item可以是 7 种不同的之一categories 对应于categories table id category 我想要一个从每个类别
  • mysql自动存储记录创建时间戳

    mysql 有什么方法可以在创建记录时自动将时间戳存储在记录行中 我试图使用时间戳 数据类型 和 current timestamp 作为默认值 但后来意识到每次更新记录时都会更新 我只需要一些可以存储创建时间戳的东西 Thanks Set
  • 通过触发器应用表的列权限

    现在 我有一个名为 Members 的表 其中包含内容 分为联系人数据 银行数据 现在 管理员应该能够创建 更新 删除用户 这些用户保存在另一个表中 该表只能访问管理员 用户应该获得自己的 mysql 用户帐户 管理员还应该能够设置权限 例
  • 如何在 SQL Server 中连接

    我的数据库没有特定的列 因此我通过开关在查询中创建了一个列 我需要的是将此列与数据库中的另一列连接起来 select certificateDuration DurationType case when certificateDuratio
  • 是否可以引用同一个表中的不同列?

    如果博客有一个 类别 表 如下所示 CREATE TABLE categories id INTEGER PRIMARY KEY AUTO INCREMENT parent id INTEGER NOT NULL name VARCHAR

随机推荐