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