我想使用不带触发器的 SQL 查询来保留表的历史记录。最简单的方法是像下面这样触发一个SELECT
并INSERT
进入历史表:
INSERT INTO history (field1, field2)
SELECT
field1,
field2
FROM
current
WHERE
field1 = condition
columns
但是,是否可以在不对ieselect *
等价物进行硬编码的情况下做到这一点?
我想使用不带触发器的 SQL 查询来保留表的历史记录。最简单的方法是像下面这样触发一个SELECT
并INSERT
进入历史表:
INSERT INTO history (field1, field2)
SELECT
field1,
field2
FROM
current
WHERE
field1 = condition
columns
但是,是否可以在不对ieselect *
等价物进行硬编码的情况下做到这一点?
您可以 - 您需要从 INSERT 列表中删除列别名,如下所示
数据库小提琴
注意:两个表的列的顺序必须相同,如果源表的模式被修改,目标表的模式也必须被修改。
免责声明:在生产代码中使用 SELECT * 被视为一种反模式 - 更改列顺序或表结构可能会导致错误。我建议不要使用这种方法。
正如已经指出的那样,如果它们具有相同的列排列,您可以将一行复制到另一个表中。
您甚至可以使用基表作为模板来创建目标表,
SELECT * INTO NewTable FROM BaseTable
如果您只想创建新表而根本不填充它,则可以使用类似的东西SELECT TOP 0 * INTO NewTable FROM BaseTable
。但我怀疑你在历史表中想要的比主存储更多:至少一个时间戳,否则每一行你所拥有的只是一袋版本,没有指示它们存在的顺序。你也可能最终得到相同的行如果存在“无操作更新”或基础数据中的更改已恢复。拥有完全相同的行可能会出现问题 - 例如:您如何删除其中一个?
您也可以通过对上述示例稍作改动来执行此操作:
当您使用 SQL Server 时,可能有一个内置选项可以为您执行此操作以及更多操作,具体取决于您需要支持的 SQL Server 版本。如果您使用的是 Azure SQL 或 SQL Server 2016 或更高版本的任何版本(包括 Express),则可以使用系统版本化时态表。
这些不仅可以在没有额外步骤或触发器的情况下为您保留数据,您还可以获得一些不错的语法糖,以便在许多常见情况下轻松查询此数据(向我展示从去年到现在的该项目的所有版本,向我展示这个项目上周的样子,告诉我整张桌子在上周四 02:34 一周的样子,...)。
他们有自己的陷阱,您仍然需要注意表结构(尽管对于某些更改,这也会自动处理),但可能正是您正在寻找的。