сжимая колонку в оракуле - PullRequest
       23

сжимая колонку в оракуле

4 голосов
/ 12 октября 2011

Допустим, у меня есть таблица со следующим определением

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

Все значения в этом dummy.col1 состоят из 7 цифр. Теперь я хочу уменьшить длину этого столбца с 9 до 7, используя команду alter. Oracle дает мне ошибку, что столбец , который нужно изменить, должен быть пустым, чтобы уменьшить точность или масштаб Имеет смысл.

Я хочу спросить, есть ли способ уменьшить размер столбца?

  • Я не могу удалить значения в столбце.
  • Я не могу скопировать значения из этого столбца в другой, поскольку в нем триллионы данных.

Ответы [ 3 ]

5 голосов
/ 12 октября 2011

Размер столбца не зависит от того, как физически хранятся данные (они имеют переменную длину)

Например, «23» в числе (2) займет точно такое же пространство, если хранится в числе (38)

Это просто ограничение на максимальное число, которое может быть сохранено в столбце, поэтому вы можете просто добавить ограничение на столбец:

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

, если вы хотите, чтобы оно прошлонемного более быстрое изменение VALIDATE на NOVALIDATE, очевидно, это не проверит достоверность существующих данных.

2 голосов
/ 12 октября 2011

Ответ Кевина превосходен.

Единственный другой способ сделать это -

переименовать существующий столбец,
создать новый столбец со старым именем и новым размером,
сгенерируйте оператор обновления, чтобы заполнить новое поле (что, как вы сказали, вы не можете сделать)
, а затем удалите переименованный столбец.

Вы уверены, что не можете найти время простоя в один из выходных для выполнения этой задачи?

0 голосов
/ 14 августа 2012

Решение № 1

Мое решение ниже сохраняет исходный порядок столбцов.
Я обнаружил, что это важно, особенно если есть готовые операторы SQL
есть (средний уровень, клиентский уровень), которые указывают на вашу базу данных, которые неявно
ВЫБИРАЕТ.

т.е.

SELECT * 
FROM tableName
WHERE ...; 

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

Вот так:

Создание DDL для
1. Таблица, содержащая столбец, размер которого вы хотите изменить
2. Все ограничения отношений, индексы, ограничения проверки, триггеры, которые ссылаются на эту таблицу.
3. Все внешние ключи других таблиц, которые ссылаются на первичный ключ этой таблицы.

Убедитесь, что каждый 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

Сохраняйте порядок столбцов, но не перестраивайте неуникальные используемые PK индексы, которые могут содержать column2.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...