更改表模式时的错误处理和数据完整性

时间:2009-06-15 09:36:45

标签: sql-server oracle schema alter-table data-integrity

我们有一些拥有大量数据集的客户,在升级过程中,我们需要修改各种表的架构(添加一些列,重命名其他列,偶尔更改数据类型,但这种情况很少见。)

以前我们一直在使用新架构的临时表,然后删除原始文件并重命名临时表,但我希望通过使用ALTER table ...来大幅提高速度。

我的问题是我需要考虑哪些数据完整性和错误处理问题?我是否应该将所有更改包含在事务中的表中(如果是,如何?)或者DBMS是否会保证ALTER操作的原子性和完整性?

我们已经强烈建议客户在开始升级之前备份他们的数据,因此应始终是后备选项。

我们需要针对SQLServer 2005和Oracle,但显然我可以添加条件代码,如果它们需要不同的方法。

4 个答案:

答案 0 :(得分:3)

仅针对Oracle的评论:

  • 表格更改是DDL,因此事务的概念不适用 - 每个DDL语句在操作期间锁定表,并且成功或失败。

  • 添加(可空!)列或重命名现有列是一个相对轻量级的过程,如果可以获取表锁,则不应出现任何问题。

  • 如果要添加/修改约束(NOT NULL或其他更复杂的检查约束),Oracle将检查现有数据以验证约束,除非您将ENABLE NOVALIDATE子句添加到约束DDL。对于大型表格,现有数据的验证可能是一个漫长的过程。

  • 如果您正在编写升级脚本以作为SQL * Plus脚本运行,请使用“每当sqlerror退出sql.sqlcode”指令在第一次失败时中止脚本,从而避免许多麻烦使部分实施的升级审查更容易。

  • 如果必须在既不能控制事务也不能错过它们的实时系统上执行升级,请考虑使用Oracle DBMS_REDEFINITION包,它自动创建临时表和触发器的临时配置以捕获 - 在“背景”中重新定义表格时的航班交易。警告 - 此选项有很多工作和陡峭的学习曲线。

答案 1 :(得分:1)

如果你使用的是SQL Server,那么ddl语句是事务性的,所以请在事务中包装(我认为这不适用于Oracle)。

我们将升级拆分为具有特定功能的单个补丁。应用了哪些补丁放在database_patch_history表中,很容易看出应用了哪些补丁以及如何将它们回滚。

正如您所说,在开始之前进行备份非常重要。

答案 2 :(得分:1)

过去我不得不做这样的改变,对数据丢失一直非常偏执。为了帮助减轻这种风险,我总是对“沙盒”数据库进行大量测试,这些数据库尽可能地在模式和数据中镜像目标数据库。在推出之前尽可能多地测试过程,就像应用程序的任何其他区域一样。

答案 3 :(得分:0)

如果您显着更改了列的任何数据类型,例如将VARCHAR更改为INT,则DBMS将发生混乱,您可能会丢失该数据。幸运的是,现在DBMS足够智能,可以在不丢失数据的情况下进行某些数据类型转换,但是您不希望在进行更改时冒着损坏任何数据类型的风险。

您不应该通过重命名列来丢失任何数据,并且肯定不会通过添加新列来删除任何数据,而是在移动您必须关注的数据时。

首先,备份整个表,包括模式和数据,所以在第二次注意时,您可以回滚到先前的模式。其次,看看你想要做出的改变,看看它们有多么激烈 - 试着弄清楚究竟需要改变什么。如果您正在进行数据类型转换,则首先将该数据推送到具有3列的外部中间表,外键(id或任何可以找到该行的内容),旧数据和新列。然后直接将旧数据推送到新列,或者在应用程序级别转换它。

如果所有类型都正确且一切都成功,请运行ALTER语句并重新填充数据库!这很简单,只需要一个逻辑思维过程。