假设我有一个具有以下定义的表
create table dummy (col1 number(9) not null)
这个dummy.col1中的所有值都有7位长。现在,我希望使用alter命令将这一列的长度从9-7减少。Oracle给出了一个错误,即要修改的列必须为空,以降低精度或缩放。合乎道理。
我想问一下,有什么工作可以缩小栏目的大小吗?
发布于 2011-10-12 14:39:36
列大小与数据的物理存储方式无关(它们是可变长度)。
例如,一个数字(2)中的“23”如果存储在一个数字(38)中,将占用完全相同的空间。
它纯粹是对可以存储在列中的最大数量的约束,因此您只需在列上添加一个约束:
ALTER TABLE dummy ADD
CONSTRAINT c1
CHECK (col1 < 9999999)
ENABLE
VALIDATE;
如果您希望它运行得更快一些,那么显然将VALIDATE
更改为NOVALIDATE
,这将不会检查现有数据的有效性。
发布于 2011-10-12 16:58:18
凯文的回答很好。
唯一的其他方法就是
重命名现有列,
创建具有旧名称和新大小的新列,
发出一个update语句来填充新字段(您说过不能这样做)
然后删除重命名的列。
您确定某个周末无法找到一些停机时间来执行此任务吗?
发布于 2012-08-14 19:26:06
解决方案#1
下面的解决方案保持原来的列顺序。
我发现这是很重要的,特别是如果有屏蔽的SQL语句。
在那里(中间层、客户层)指向执行隐式操作的数据库。
选择。
即
SELECT *
FROM tableName
WHERE ...;
INSERT INTO copyTableName(column1,column2,column3,...)
SELECT *
FROM tableName
WHERE ...;
下面是:
生成DDL
确保每个表引用对象DDL是独立的,与
创建表DDL。
你会有这样的东西
/* 1. The table containing the column you intend to resize */
CREATE TABLE tableName
(
column1 TYPE(size) [DEFAULT value] [NOT] NULL,
column2 TYPE(size) [DEFAULT value] [NOT] NULL,
column3 TYPE(size) [DEFAULT value] [NOT] NULL,
...
)
TABLESPACE tsName
[OPTIONS];
/* 2. All the relationship constraints, indexes, check constraints, triggers that reference that table. */
CREATE INDEX indexName ON tableName
(column1)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
CREATE INDEX compositeIndexName ON tableName
(column1,column2,...)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
CREATE UNIQUE INDEX pkName ON tableName
(column2)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
ALTER TABLE tableName ADD (
CHECK (column4 IS NOT NULL));
ALTER TABLE tableName ADD (
CONSTRAINT pkName
PRIMARY KEY
(column2)
USING INDEX
TABLESPACE INDX);
ALTER TABLE tableName ADD (
CONSTRAINT fkName
FOREIGN KEY (column2)
REFERENCES otherTable (column2));
/* 3. All the foreign keys of other tables that reference the primary key of this table. */
ALTER TABLE otherTableName ADD (
CONSTRAINT otherTableFkName
FOREIGN KEY (otherTableColumn2)
REFERENCES tableName (column1));
只复制CREATE TABLE
语句,更改表名和
缩小要修改的列的大小:
CREATE TABLE tableName_YYYYMMDD
(
column1 TYPE(size) [DEFAULT value] [NOT] NULL,
column2 TYPE(reducedSize) [DEFAULT value] [NOT] NULL,
column3 TYPE(size) [DEFAULT value] [NOT] NULL,
...
)
TABLESPACE tsName
[OPTIONS];
将tableName
中的数据插入tableName_YYYYMMDD
:
INSERT /* APPEND */ INTO tableName_YYYYMMDD(
column1 ,
column2 ,
column3 ,
... )
SELECT
column1 ,
column2 ,
column3 ,
...
FROM tableName;
COMMIT;
删除引用原始表的所有对象。
另外,删除引用tableName主键pkName的所有外键。
别担心,您已经保存了DDL,这样就可以重新创建它们了。
注意,我在从tableName复制数据后删除了索引。
我这样做是因为其中一个索引可能会在
以上选择使操作完成速度更快。
DROP INDEX indexName ;
DROP INDEX compositeIndexName ;
DROP UNIQUE INDEX pkName ;
ALTER TABLE tableName DROP CONSTRAINT pkName ;
ALTER TABLE tableName DROP CONSTRAINT fkName ;
ALTER TABLE otherTableName DROP CONSTRAINT otherTableFkName ;
放下原来的桌子。
DROP TABLE tableName;
重命名新表。
ALTER TABLE tableName_YYYYMMDD RENAME TO tableName;
重新创建以前保存的DDL语句中的所有引用对象。
/* 2. All the relationship constraints, indexes, check constraints, triggers that reference that table. */
CREATE INDEX indexName ON tableName
(column1)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
CREATE INDEX compositeIndexName ON tableName
(column1,column2,...)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
CREATE UNIQUE INDEX pkName ON tableName
(column2)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
ALTER TABLE tableName ADD (
CHECK (column4 IS NOT NULL));
ALTER TABLE tableName ADD (
CONSTRAINT pkName
PRIMARY KEY
(column2)
USING INDEX
TABLESPACE INDX);
ALTER TABLE tableName ADD (
CONSTRAINT fkName
FOREIGN KEY (column2)
REFERENCES otherTable (column2));
/* 3. All the foreign keys of other tables that reference the primary key of this table. */
ALTER TABLE otherTableName ADD (
CONSTRAINT otherTableFkName
FOREIGN KEY (otherTableColumn2)
REFERENCES tableName (column1));
解决方案#2
保持列的顺序,但不要重建可能包含column2的非唯一使用的PK索引。
ALTER TABLE tableName ADD (column2Copy TYPE(reducedSize));
UPDATE tableName SET column2Copy = column2;
ALTER TABLE tableName MODIFY (column2 TYPE(size) NULL);
ALTER TABLE tableName DROP CONSTRAINT pkName;
DROP INDEX pkName;
UPDATE tableName SET column2 = null;
ALTER TABLE tableName MODIFY (column2 TYPE(reducedSize));
UPDATE tableName SET column2 = column2Copy;
ALTER TABLE tableName DROP COLUMN column2Copy;
CREATE UNIQUE INDEX pkName ON tableName
(column2)
NOLOGGING
TABLESPACE INDX
NOPARALLEL;
ALTER TABLE tableName ADD (
CONSTRAINT pkName
PRIMARY KEY
(column2)
USING INDEX
TABLESPACE INDX);
COMMIT;
https://stackoverflow.com/questions/7741468
复制相似问题