我当前分配到的程序要求在实际处理之前将表的内容复制到备份表。
在代码审查期间,一位同事指出
INSERT INTO BACKUP_TABLE
SELECT *
FROM PRIMARY_TABLE
风险太大,因为表可能具有不同的列和不同的列顺序。
我也受到不创建/删除/重命名表的约束。~叹气~
表中的列预计会发生变化,因此简单地对列名进行硬编码并不是我正在寻找的解决方案。
我正在寻找一种合理的、无风险的方式来完成这项工作的想法。
备份表是否保留?它是永久保留数据,还是只是当前值的副本?
无法创建/删除/重命名/复制太糟糕了。否则,如果它是短期的,只是在出现问题时使用,那么您可以在处理开始时将其删除并执行类似的操作
create table backup_table as select * from primary_table;
您最好的选择可能是使选择明确,如
insert into backup_table (<list of columns>) select <list of columns> from primary_table;
您可以通过从数据字典构建一个 SQL 字符串来生成它,然后立即执行。但是,如果 backup_table 不包含 primary_table 中的所有重要列,您仍然会面临风险。
可能只想使其明确,如果 backup_table 不存在,或者 primary_table 中的任何列不在 backup_table 中,则会引发重大错误。
您多久更改一次表格的结构?如果结构没有改变,您的方法应该可以正常工作。我个人认为您的 DBA 应该为您提供删除备份表并重新创建它的机制,例如存储过程。在我上一份工作中,我们在截断某些表时遇到了类似的情况,因为截断通常比DELETE FROM TABLE;
.
您是否有理由不能只列出表格中的列?所以
INSERT INTO backup_table( col1, col2, col3, ... colN )
SELECT col1, col2, col3, ..., colN
FROM primary_table
当然,这需要您在更改其中一个表的定义时重新访问代码以确定是否需要进行代码更改,但这通常是为了使自己免受列顺序差异、列差异的影响而付出的小代价名称,以及表定义中不相关的差异。
如果我遇到这种情况,我会在问题开始时检索两个表的列定义。然后,如果它们相同,我将继续进行简单的操作:
INSERT INTO BACKUP_TABLE
SELECT *
FROM PRIMARY_TABLE
如果它们不同,我只会在备份表中没有缺少关键列的情况下继续。在这种情况下,我将使用此表单作为备份副本:
INSERT INTO BACKUP_TABLE (<list of columns>)
SELECT <list of columns>
FROM PRIMARY_TABLE
但是我也担心如果我只是因为错误而停止程序会发生什么,所以我什至可能有一个备份计划,我会为两个表中的列使用第二种形式,并转储一个文本文件与 PK 和备份中缺少的任何列。即使程序似乎正常完成,也要记录一个错误。这样,如果发生最坏的情况,您可以恢复数据。
确实,这是应该解决的不良流程的症状,但是防御性编程可以帮助使其成为其他人的问题,而不是您的问题。如果他们没有注意到日志错误消息告诉他们有关缺少列的文本转储,那么这不是您的错。
但是,如果您不进行防御性编码,并且最坏的情况发生了,那部分原因将是您的错。
您可以尝试以下方法:
CREATE TABLE secondary_table AS SELECT * FROM primary_table;
不确定这是否会自动复制数据。如果不:
CREATE TABLE secondary_table AS SELECT * FROM primary_table LIMIT 1;
INSERT INTO secondary_table SELECT * FROM primary_table;
编辑:
抱歉,没有完全阅读您的帖子:尤其是约束部分。恐怕我不知道怎么做。我的猜测是在创建冗长的插入/选择查询之前使用一个首先描述两个表并比较它们的过程。
不过,如果您使用的是备份表,我认为它与原始表完全匹配非常重要。