AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 6320
Accepted
Martin
Martin
Asked: 2011-09-30 02:31:27 +0800 CST2011-09-30 02:31:27 +0800 CST 2011-09-30 02:31:27 +0800 CST

在事务中修改表结构?

  • 772

在 Oracle(可能还有其他地方)中,执行 ALTER TABLE 语句将对当前事务执行隐式提交。

我们有一个工具(用 Java 编写)应该通过以下方式修改模式:

  • 添加一些列
  • 删除一些列
  • 使用新的模式布局更新描述表

编写的工具将向用户显示当前模式布局并允许他修改它。(基本上在某些表中添加或删除自定义“属性”列)一旦他满意,他就可以应用他的更改。

请注意:基本模式布局,以及您需要 ALTER TABLE 来更改某些内容的事实是由标准预定义的,我们无法更改,因为其他工具将不再起作用。

现在的问题是我们不能在单个事务中运行这些更改,因为 AFAIK,不可能在一个事务中执行多个 ALTER TABLE 语句。

如果在应用更改时出现问题,我们有哪些选项可以“回滚”到初始状态?

注意:这里有人提出了 RESTORE POINT + FLASHBACK ——从这个(Java)工具调用它是个好主意吗?(在某些应该使用该工具的站点,我们不会完全控制数据库实例。)

注:Oracle 10g2 及以上

oracle schema
  • 6 6 个回答
  • 5544 Views

6 个回答

  • Voted
  1. Best Answer
    Chris Saxon
    2011-09-30T03:30:53+08:002011-09-30T03:30:53+08:00

    由于 DDL 隐式提交,“回滚”更改的唯一方法是构造反向操作并将其应用于还原更改,如 a_horse_with_no_name 所述。

    然而,构建这样的回滚并不总是那么简单。如果数据可以在类型修改 (varchar2(10) -> varchar2(50), number -> varchar2) 之间写入表并回滚,那么您还必须检查新数据在恢复时是否有效原始类型(或执行一些转换)。请注意,在大型表上删除列可能需要一些时间并生成大量重做。

    您还必须警惕由于这些更改而使数据库和其他应用程序依赖项上的任何存储过程无效。

    在这种情况下,闪回选项对您没有帮助。对表进行 DDL 更改后,您无法使用闪回将其恢复到之前的状态。尝试这样做会给你错误:

    ORA-01466: 无法读取数据 - 表定义已更改

    闪回您的完整数据库将是矫枉过正,也无法从 Java 应用程序 - 您需要关闭然后挂载数据库才能完成此操作。

    这一切都提出了你的工具是做什么的问题。如果您只需要一个 GUI 供人们编辑表,那么像 Oracle SQL Data Modeler 之类的工具可以完成此操作并为您生成 DDL 脚本。然后可以对这些进行验证、测试、构建适当的回滚并将其应用于数据库。修改(生产)数据库的结构应该小心并经过测试,以确保所有更改都是有效的!

    • 5
  2. a_horse_with_no_name
    2011-09-30T02:41:47+08:002011-09-30T02:41:47+08:00

    我能想到的唯一方法(不迁移到支持事务 DDL 的 DBMS)是编写自己的“DDL 事务”处理,在其中创建相应的语句来回滚您所做的实际更改。

    “回滚” ADD COLUMN 非常简单,因为您只需要删除该列。要回滚 DROP COLUMN,我看到的唯一选择是先重命名该列,然后在一切成功后删除所有重命名的列。要回滚“虚拟删除”,您只需将列重命名为原始名称。

    另一种选择可能是在修改它们之前创建表的副本,例如使用CREATE TABLE backup_table AS SELECT * FROM original_table(但如果表真的很大,这显然不是一个好的解决方案)

    使用闪回可能不是很可靠,因为您不能依赖闪回数据的可用性。保证闪回时间的默认值为15 分钟。但是 DBA 可以自由选择较小的值。

    • 2
  3. Todd Pierce
    2011-10-01T07:45:02+08:002011-10-01T07:45:02+08:00

    Oracle 在 11gR2 中添加了一个基于版本的重新定义功能,用于升级应用程序模式,大部分是在线的。您可能可以使用它来实现您的目标。

    • 2
  4. Jimbo
    2011-09-30T07:28:53+08:002011-09-30T07:28:53+08:00

    对一组临时表进行所有更改。

    当一切顺利完成后,将所有更改应用到真实表格。

    • 1
  5. Phill W.
    2018-11-15T03:35:27+08:002018-11-15T03:35:27+08:00

    Oracle DDL 语句隐式提交。这是我使用的唯一DBMS。

    Oracle 的“闪回表”可以将表回退到更早的时间点……但它在对该表的结构(即 DDL)更改时 不起作用。

    “闪回数据库”使用不同的机制,但会将整个数据库恢复到更改之前,您可能不允许这样做。

    另一个没有人提到的选项是DBMS_REDEFINITION单体。 这是一个巨大的、由 Oracle 提供的包,应该为您管理所有这些,使您的表更改透明、无缝并避免 [几乎] 任何服务中断。它很大而且很复杂,但它可能值得投资来掌握它。

    • 1
  6. Roeland Van Heddegem
    2013-09-17T02:50:11+08:002013-09-17T02:50:11+08:00

    我认为您最好添加一个结构,您的客户认为他们正在添加列,但实际上他们只是在表中添加记录,例如:“Table_Column_DEF”。然后,您只需要默认表和“Table_Column_DEF”之间的链接表,您还可以在其中存储值。

    使用这种方法,您的客户可以添加他们想要的任何列,并且可以在 1 个事务中完成此操作。您可以从回滚、闪回等中受益……您当然需要考虑一些权衡:

    1) 价值栏:

    • 每个可能的数据类型都有 1 个值列,并将所有内容存储在 varchar2、clob 或 blob 中。
    • 每个可能的数据类型的值列...

    2) 性能

    3)查询:您必须动态构建它。循环遍历所有“Table_Column_DEF”记录并使用“选择(从 LinkTable 中选择 Value_Int where ...)Value_Int,... from ...”添加它们

    • 0

相关问题

  • Oracle 中的数据库备份 - 导出数据库还是使用其他工具?

  • ORDER BY 使用文本列的自定义优先级

  • 舒服的sqlplus界面?[关闭]

  • 如何在数据库中找到最新的 SQL 语句?

  • 如何使用正则表达式查询名称?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve