2011-10-12 47 views
4

可以說我有一個表,定義如下萎縮在Oracle列

create table dummy (col1 number(9) not null) 

在此dummy.col1的所有值均爲7位數長。現在我想使用alter命令從9 - 7減少此列的長度。甲骨文給我的錯誤,列被修改必須是空的,以降低精度或規模。說得通。

我想問一下,是否有任何解決方法來減小列大小?

  • 我無法刪除列中的值。
  • 我無法將此列中的值複製到另一列,因爲它有數以萬億計的數據。

回答

5

該柱尺寸必須如何數據的物理存儲沒有關係(它們是可變長度)

例如如果存儲在數字中,則數字(2)中的'23'將完全相同(38)

它純粹是對可存儲在列中的最大數量的約束,因此您可以只添加一個約束在列:

ALTER TABLE dummy ADD 
CONSTRAINT c1 
CHECK (col1 < 9999999) 
ENABLE 
VALIDATE; 

,如果你想讓它去的快一點改變VALIDATENOVALIDATE顯然這不會檢查現有數據的有效性。

+0

它不會減少此列所消耗的額外存儲空間嗎?即13位數字 –

+0

數字被存儲爲可變長度數據,該大小被用作約束。請參閱:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1619552483055並在頁面中搜索55 –

2

凱文的答案非常好。

唯一的其他方式來做到這一點是

重命名現有列,
創建與舊名稱的新列和新的大小,
問題的更新語句來填充新字段(你說你不能這樣做)
然後刪除重命名的列。

你確定你無法在一個週末找到一些停機時間來執行此任務嗎?

0

解決方案#1

下面我的解決方案保持原有列的順序。
我發現這很重要,尤其是如果出現罐裝SQL語句
那裏(中間層,客戶端層)指向您的數據庫,並且隱含
SELECTs。

SELECT * 
FROM tableName 
WHERE ...; 

INSERT INTO copyTableName(column1,column2,column3,...) 
    SELECT * 
    FROM tableName 
    WHERE ...; 

這裏所說:

生成的DDL爲
1.表包含您打算調整
2.所有的關係約束,索引,檢查約束之列,觸發器引用該表。 3 3。引用該表主鍵的其他表的所有外鍵。

確保每個表引用對象DDL是獨立的,獨立於CREATE TABLE 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]; 

插入從tableNametableName_YYYYMMDD的數據:

INSERT /* APPEND */ INTO tableName_YYYYMMDD(
    column1 , 
    column2 , 
    column3 , 
    ... ) 
    SELECT 
     column1 , 
     column2 , 
     column3 , 
     ...  
    FROM tableName; 
COMMIT; 

刪除所有引用原始表的對象。
另外,刪除引用tableName主鍵pkName的所有外鍵。
別擔心,你已經保存了DDL,所以你可以重新創建它們。
請注意,我在將數據從tableName複製出來後刪除索引。
我這樣做是因爲可能在SELECT上面的
中使用其中一個索引,以便操作更快完成。

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;