如何在oracle的特定位置插入一列而不删除并重新创建表?

Ami*_*mit 24 oracle oracle11g

我有一个特定的场景,我必须在Oracle的现有表中插入两个新列.我无法放弃并重新创建表格.那么它可以通过任何方式实现吗?

小智 21

Amit-

我不相信你可以在任何地方添加一个列,但是在创建表之后会在表的末尾添加一个列.一种解决方案可能是试试这个:

CREATE TABLE MY_TEMP_TABLE AS
SELECT *
FROM TABLE_TO_CHANGE;
Run Code Online (Sandbox Code Playgroud)

删除要添加列的表:

DROP TABLE TABLE_TO_CHANGE;
Run Code Online (Sandbox Code Playgroud)

您可以从头开始重建现有表,添加您希望的列.我们假设您要在本练习中添加名为"COL2和COL3"的列.

现在将数据插回到新表中:

INSERT INTO TABLE_TO_CHANGE (COL1, COL2, COL3, COL4) 
SELECT COL1, 'Foo', 'Bar', COL4
FROM MY_TEMP_TABLE;
Run Code Online (Sandbox Code Playgroud)

将数据插入"新旧"表后,可以删除临时表.

DROP TABLE MY_TEMP_TABLE;
Run Code Online (Sandbox Code Playgroud)

这通常是我想在特定位置添加列时的操作.显然,如果这是一个生产在线系统,那么它可能不实用,但只是一个潜在的想法.

-CJ


dr *_*chu 7

在 12c 中,您可以利用设置为从不可见到可见的列显示为表的最后一列这一事实: 提示和技巧:Oracle 数据库 12c 中的不可见列

也许这就是@jeffrey-kemp 在他的评论中所说的“技巧”,但那里的链接不再有效。

例子:

ALTER TABLE my_tab ADD (col_3 NUMBER(10));
ALTER TABLE my_tab MODIFY (
  col_1 invisible,
  col_2 invisible
);
ALTER TABLE my_tab MODIFY (
  col_1 visible,
  col_2 visible
);
Run Code Online (Sandbox Code Playgroud)

现在 col_3 将首先显示在SELECT * FROM my_tab语句中。

注意:这不会改变磁盘上列的物理顺序,但在大多数情况下,这不是您想要做的。如果你真的想改变物理顺序,你可以使用 DBMS_REDEFINITION 包。

  • 这应该是答案!作品完美! (2认同)
  • 链接文章不见了,可以在[此处](https://web.archive.org/web/20180705054649/https://www.oracle.com/technetwork/articles/database/invisible-columns-odb12c-2331522 .html) (2认同)

小智 6

虽然这有点旧,但我想添加一个稍微改进的版本,它真正改变了列顺序.以下是步骤(假设我们有一个表格TAB1,列COL1,COL2,COL3):

  1. 向表TAB1添加新列:
alter table TAB1 add (NEW_COL number);
Run Code Online (Sandbox Code Playgroud)
  1. 更改列顺序时"复制"表到临时名称并重命名新列:
create table tempTAB1 as select NEW_COL as COL0, COL1, COL2, COL3 from TAB1;
Run Code Online (Sandbox Code Playgroud)
  1. 删除现有表:
drop table TAB1;
Run Code Online (Sandbox Code Playgroud)
  1. 将临时表名重命名为刚删除的表名:
rename tempTAB1 to TAB1;
Run Code Online (Sandbox Code Playgroud)


小智 5

您(仍然)无法使用ALTER TABLE选择列的位置:它只能添加到表的末尾.您显然可以按任何顺序选择列,因此除非您使用SELECT*FROM列顺序,否则不应该是一个大问题.

如果您确实必须按特定顺序使用它们并且无法删除并重新创建表,那么您可以删除并重新创建列: -

首先复制表格

CREATE TABLE my_tab_temp AS SELECT * FROM my_tab;
Run Code Online (Sandbox Code Playgroud)

然后删除要插入的列之后的列

ALTER TABLE my_tab DROP COLUMN three;
Run Code Online (Sandbox Code Playgroud)

现在添加新列(本例中为两列)和删除的列.

ALTER TABLE my_tab ADD (two NUMBER(2), three NUMBER(10));
Run Code Online (Sandbox Code Playgroud)

最后,为重新创建的列添加数据

UPDATE my_tab SET my_tab.three = (SELECT my_tab_temp.three FROM my_tab_temp WHERE my_tab.one = my_tab_temp.one);
Run Code Online (Sandbox Code Playgroud)

显然,您的更新很可能会更复杂,您将不得不处理索引和约束,并且在某些情况下(LOB列等)将无法使用它.此外,这是一个非常可怕的方式 - 但表格将始终存在,您将按照您想要的顺序结束列.但是,列顺序真的那么重要吗?