Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 更改多个表的列长度_Sql_Database_Oracle_Orm_Ddl - Fatal编程技术网

Sql 更改多个表的列长度

Sql 更改多个表的列长度,sql,database,oracle,orm,ddl,Sql,Database,Oracle,Orm,Ddl,因此,我们刚刚发现Oracle DBMS中的254个表有一个名为Foo的列,其长度错误-Number10而不是Number3 该foo列是表PK的一部分。 这些表还有其他表,其中有forigen键 我所做的是: 使用临时表备份表。 已禁用表的forigen键。 使用foo列禁用PK。 为所有行的foo列设置为空。 恢复了以上所有内容 但现在我们发现不仅仅是几张桌子,而是254张桌子 有没有一种简单的方法,或者至少比这更简单的方法来改变列的长度 另外,我有DBA权限。我们所做的是: CREATE

因此,我们刚刚发现Oracle DBMS中的254个表有一个名为Foo的列,其长度错误-Number10而不是Number3

该foo列是表PK的一部分。 这些表还有其他表,其中有forigen键

我所做的是:

使用临时表备份表。 已禁用表的forigen键。 使用foo列禁用PK。 为所有行的foo列设置为空。 恢复了以上所有内容 但现在我们发现不仅仅是几张桌子,而是254张桌子

有没有一种简单的方法,或者至少比这更简单的方法来改变列的长度

另外,我有DBA权限。

我们所做的是:

CREATE TABLE <table_name_backup> as SELECT *  <table_name>;
DELETE <table_name>;    
ALTER TABLE <table_name> MODIFY (Foo NUMBER(3));
INSERT INTO <table_name> SELECT * FROM <table_name_backup>;
DROP <table_name_backup>;
对于所有表格。

我们所做的是:

CREATE TABLE <table_name_backup> as SELECT *  <table_name>;
DELETE <table_name>;    
ALTER TABLE <table_name> MODIFY (Foo NUMBER(3));
INSERT INTO <table_name> SELECT * FROM <table_name_backup>;
DROP <table_name_backup>;

对于所有的表。

您的解决方案是可行的,但工作量很大,并且意味着停机

由于数字3在物理上与数字10完全相同,具有更强的约束,因此您可以添加检查约束,并在不停机的情况下获得相同的逻辑约束:

LOOP
   ALTER TABLE <table_name> ADD CONSTRAINT <table_foo_chk> CHECK (foo < 1000);
END LOOP;

您的解决方案可以工作,但工作量很大,并且意味着停机

由于数字3在物理上与数字10完全相同,具有更强的约束,因此您可以添加检查约束,并在不停机的情况下获得相同的逻辑约束:

LOOP
   ALTER TABLE <table_name> ADD CONSTRAINT <table_foo_chk> CHECK (foo < 1000);
END LOOP;

有一种更简单的方法可以生成所需的脚本、使用系统表和动态生成DDL。缺点是这需要停机时间。还要注意,我使用的是命令而不是delete,这应该更快

假设一个简单的表如下所示:

create table a ( 
   foo number(10)
 , bar number(10)
 , constraint pk_a primary key (foo)
 , constraint fk_a foreign key ( bar ) references a(foo )
  );
这是一个看起来不讨人喜欢的查询

select cmd
  from ( 
select table_name
     , 1 as stage -- Just used to order by at the end.
     , 'create table ' || table_name || '_backup as select * from ' 
                      || table_name || ';' || chr(10) as cmd
       -- chr(10) is LF
  from user_tab_columns -- View of all columns
 where column_name = 'FOO'
   and data_precision = 10 -- Length of the number
 union all
select table_name
     , 3 as stage
     ,  'truncate table ' || table_name || ';' || chr(10) -- Remove all data
       || 'alter table ' || table_name 
               || ' modify ( foo number(3));' || chr(10)
       || 'insert into ' || table_name || ' select * from ' 
            || table_name || '_backup;' || chr(10)
       || 'drop table ' || table_name || '_backup;' as cmd
  from user_tab_columns
 where column_name = 'FOO'
   and data_precision = 10
 union all
select ut.table_name
     , 2 as stage
       -- Disable the constraint
     , 'alter table ' || uc.table_name || ' disable constraint ' 
            || uc.constraint_name || ';' || chr(10) as cmd
  from user_constraints uc -- All named constraints
  join user_tab_columns ut
    on uc.table_name = ut.table_name
 where ut.column_name = 'FOO'
   and ut.data_precision = 10 
   and constraint_type = 'R' -- Foreign Key constraints (see link)
 union all
select ut.table_name
     , 4 as stage
     , 'alter table ' || uc.table_name || ' enable constraint ' 
          || uc.constraint_name || ';' || chr(10) as cmd
  from user_constraints uc
  join user_tab_columns ut
    on uc.table_name = ut.table_name
 where ut.column_name = 'FOO'
   and ut.data_precision = 10
   and constraint_type = 'R'
       )
 order by stage
将产生以下结果:

create table A_backup as select * from A; -- Create your backup
alter table A disable constraint FK_A; -- Disable FKs
truncate table A; -- Remove all data in the table
alter table A modify ( foo number(3)); -- Reduce the size of the column
insert into A select * from A_backup; -- Replace all the data
drop table A_backup; -- Drop the backup
alter table A enable constraint FK_A; -- Re-enable FKs
由于列阶段的原因,这将不是一个表一个表地完成,而是一个阶段一个阶段地完成,以便同时禁用所有约束,从而避免出现问题。如果你害怕,那么就从查询中删除掉_备份表;这意味着无论发生什么问题,你都是安全的

如果您在SQL*中运行此功能,并且还希望在sqlerror退出时包含它,以便在出现问题(例如没有更多表空间)时,不会截断未备份的内容。它可能几乎值得一步一步地运行,这样您就知道一切都已正确完成


我建议在不同的用户上使用几个表来测试它,以确保它可以完成您需要的所有操作。

有一种更简单的方法来生成您想要的脚本,使用系统表并动态生成DDL。缺点是这需要停机时间。还要注意,我使用的是命令而不是delete,这应该更快

假设一个简单的表如下所示:

create table a ( 
   foo number(10)
 , bar number(10)
 , constraint pk_a primary key (foo)
 , constraint fk_a foreign key ( bar ) references a(foo )
  );
这是一个看起来不讨人喜欢的查询

select cmd
  from ( 
select table_name
     , 1 as stage -- Just used to order by at the end.
     , 'create table ' || table_name || '_backup as select * from ' 
                      || table_name || ';' || chr(10) as cmd
       -- chr(10) is LF
  from user_tab_columns -- View of all columns
 where column_name = 'FOO'
   and data_precision = 10 -- Length of the number
 union all
select table_name
     , 3 as stage
     ,  'truncate table ' || table_name || ';' || chr(10) -- Remove all data
       || 'alter table ' || table_name 
               || ' modify ( foo number(3));' || chr(10)
       || 'insert into ' || table_name || ' select * from ' 
            || table_name || '_backup;' || chr(10)
       || 'drop table ' || table_name || '_backup;' as cmd
  from user_tab_columns
 where column_name = 'FOO'
   and data_precision = 10
 union all
select ut.table_name
     , 2 as stage
       -- Disable the constraint
     , 'alter table ' || uc.table_name || ' disable constraint ' 
            || uc.constraint_name || ';' || chr(10) as cmd
  from user_constraints uc -- All named constraints
  join user_tab_columns ut
    on uc.table_name = ut.table_name
 where ut.column_name = 'FOO'
   and ut.data_precision = 10 
   and constraint_type = 'R' -- Foreign Key constraints (see link)
 union all
select ut.table_name
     , 4 as stage
     , 'alter table ' || uc.table_name || ' enable constraint ' 
          || uc.constraint_name || ';' || chr(10) as cmd
  from user_constraints uc
  join user_tab_columns ut
    on uc.table_name = ut.table_name
 where ut.column_name = 'FOO'
   and ut.data_precision = 10
   and constraint_type = 'R'
       )
 order by stage
将产生以下结果:

create table A_backup as select * from A; -- Create your backup
alter table A disable constraint FK_A; -- Disable FKs
truncate table A; -- Remove all data in the table
alter table A modify ( foo number(3)); -- Reduce the size of the column
insert into A select * from A_backup; -- Replace all the data
drop table A_backup; -- Drop the backup
alter table A enable constraint FK_A; -- Re-enable FKs
由于列阶段的原因,这将不是一个表一个表地完成,而是一个阶段一个阶段地完成,以便同时禁用所有约束,从而避免出现问题。如果你害怕,那么就从查询中删除掉_备份表;这意味着无论发生什么问题,你都是安全的

如果您在SQL*中运行此功能,并且还希望在sqlerror退出时包含它,以便在出现问题(例如没有更多表空间)时,不会截断未备份的内容。它可能几乎值得一步一步地运行,这样您就知道一切都已正确完成


我建议用几个表在不同的用户上进行测试,以确保它能满足您的所有需要。

没有级联删除,例如不需要的行为?乍一看似乎很危险,但我可能会错过一些东西。@RaphaëlAlthaus。哦,是的,我必须禁用引用表中的所有外键。我很快会在答案中添加这一点。{是我错过了一些东西…;}没有级联删除,例如不想要的行为?乍一看似乎很危险,但我可能会错过一些东西。@RaphaëlAlthaus。哦,是的,我必须禁用引用表中的所有外键。我很快会在答案中添加这一点。{是我漏掉了一些东西…;}这样做的缺点是,所有的插入和更新都必须永远根据该约束进行检查。@ben:与生成重做/撤消、从缓存中获取块等的大量工作相比,单次检查约束产生了无法检测到的开销。。。由更新/插入暗示。这对我没有帮助,因为我将它们设为3号,因为我们开始使用实体框架,它将一些映射为short,一些映射为int。无论如何,谢谢。这样做的缺点是,所有插入和更新都必须永远根据该约束进行检查。@ben:单一检查约束会产生一个与生成重做/撤消、从缓存获取块等的大量工作相比,无法检测到的开销量。。。这对我没有帮助,因为我们开始使用实体框架,所以我把它们设为3号
d它将一些映射为短,一些映射为int。无论如何,谢谢。谢谢!你能给上面看起来不好看的代码添加注释吗。我不想运行我不完全理解的DDL查询。我已经尝试让它更容易理解。。。并补充了一些警告:谢谢,我真的很感谢你的帮助和努力。最后一件事,chr10在做什么?我从来没有在查询中看到过这样的事情。没问题,我经常做类似的事情!这只是一个换行码ASCII 10,chr编码。这意味着在打印结果时,为了避免联合加载而连接在一起的语句位于不同的行上。谢谢!你能给上面看起来不好看的代码添加注释吗。我不想运行我不完全理解的DDL查询。我已经尝试让它更容易理解。。。并补充了一些警告:谢谢,我真的很感谢你的帮助和努力。最后一件事,chr10在做什么?我从来没有在查询中看到过这样的事情。没问题,我经常做类似的事情!这只是一个换行码ASCII 10,chr编码。这意味着在打印结果时,为了避免联合加载而连接在一起的语句位于不同的行上。