【问题标题】:loop and change all record numbers in Firebird database循环并更改 Firebird 数据库中的所有记录号
【发布时间】:2018-08-06 07:11:50
【问题描述】:

我有一个数据库表,其中包含使用生成器创建的唯一记录号,但由于代码错误(设置生成器)记录号突然变大,因为跳过了许多数字。我想重写从 1 开始的所有记录号,并以总记录号结束。应用程序将花费大量时间。 正如我从 Firebird 的文档中看到的,使用循环应该是一个简单的任务,但我没有使用 Firebird 编程的经验,我只使用简单的 SQL 语句,有人可以帮忙吗?

【问题讨论】:

  • 这是对生成器的滥用,它们旨在生成事务外数字,当事务回滚或不以插入结束时有间隙。 // 阅读 PSQL 教程,例如存储过程。您可以使用“EXECUTE BLOCK”运行它们,您需要声明内部整数变量,将其设置为零,并使用 begin-end 进行“for select ... order by ID-column as [named cursor name]”循环,在循环中,您将“更新 ... set ID-column = :local-ID-variable where current of [named cursor name]”,然后增加变量。
  • 然后在提交之后你会将生成器移动到最大 ID。注意:它仍然需要很长时间,因为它实际上需要复制数据库中的整个表。在此处阅读相应的主题:firebirdsql.org/file/documentation/reference_manuals/… - 第 6 章为 SELECT(包括 FOR SELECT 和“作为游标”子句)和 UPDATE ... WHERE CURRENT OF 以及 PSQL 变量和循环(第 7 章)。
  • 谢谢,我设法创建了执行块,但正如我在下一个解决方案中评论的那样,要复杂得多。无论如何,我学到了一些东西:)

标签: firebird firebird2.5


【解决方案1】:

其实不需要编写循环,简单的update 语句就可以了。首先,重置生成器:

SET GENERATOR my_GEN TO 0;

然后更新所有记录并为其分配新的 id

update tab set recno = gen_id(my_GEN, 1) order by recno asc;

它假定所有对recno 字段的引用都是通过带有ON UPDATE CASCADE 的外键,否则你要么弄乱你的数据,要么更新失败。

在此操作期间,数据库中应该没有其他用户!

话虽如此,你真的不应该关心你的记录数字的差距。

【讨论】:

  • 这是一个优雅的解决方案,但在我的情况下,任何解决方案似乎都很复杂,因为我需要删除包括主键在内的所有约束,这是不可能的,因为它用于外键定义......无论如何正如你所说,最好还是原样离开。我担心整数大小(当前记录数超过 10 000 000),但我有时间达到 2,147,483,647 :)
  • 现在我想你不能以随机顺序更新它们,记录必须以“当前id顺序”更新,即update ... order by recno asc。这样,您就不会尝试分配仍在使用中的新 id(因此失败),即如果您有记录 id 1、3,......那么首先您的更新会将 1 分配给记录 1(即没有更改),然后将 2 分配给记录 3,依此类推。
  • @Danxy 也许您可以将 FK 约束更改为级联约束。但是,这又是对生成器概念的滥用……还有关于应用程序外引用的事情。就像您的雇主给另一位员工写一封电子邮件,谈论“文档#12345”。一周后,有人删除了文档 12200-12250,突然该引用的文档被重新编号为 12295。然后员工 2 阅读电子邮件(甚至纸质蜗牛邮件),打开文档 #12345 - 在不知道它与不相关的情况下工作不同的。
  • ain,是的,你说得对,后来我想到了。我按日期列排序。 Arioch,我不希望有这样的问题,因为关系表是刚刚添加的,项目中的新表......好吧,我会看看该怎么做如果我有额外的时间(这几乎是无法实现的愿望:)
  • @Danxy 如果您担心整数大小,我会尽快建议您采取措施改用BIGINT(尽管这会更复杂,而不仅仅是重新编号)。跨度>
猜你喜欢
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 2012-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 1970-01-01
相关资源
最近更新 更多