Co się stanie, gdy zmodyfikujesz (zmniejszysz) długość kolumny?

10

Powiedzmy, że mam dwie kolumny typu NUMBER(bez precyzji i skali) i VARCHAR(300). Widziałem, że te kolumny są zbyt duże dla moich danych, więc chcę je zmodyfikować do NUMBER(11)i VARCHAR(10). Więc jeśli uruchomię tę instrukcję SQL:

ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
  • Czy będę mógł to zrobić w niepustej kolumnie?
  • Jeśli tak, to co jeśli Jeśli jest jedna wartość większa niż NUMBER(10), wyrocznia opowie mi o tym?
  • Czy domyślne wartości kolumn pozostaną niezmienione, jeśli zostały wcześniej zdefiniowane?
  • Czy opcja zerowania kolumny pozostanie niezmieniona?
  • Czy podstawowy, obcy, unikalny klucz w tej kolumnie pozostanie niezmieniony?
  • Czy ograniczenia dotyczące tych kolumn pozostaną niezmienione?
  • Czy indeksy w tych kolumnach pozostaną niezmienione?

Czy jest jakaś oficjalna dokumentacja odpowiadająca na moje pytania?

mnowotka
źródło

Odpowiedzi:

12

Oracle Administratorzy przewodnik mówi, co następuje:

Użyj instrukcji ALTER TABLE ... MODIFY, aby zmodyfikować istniejącą definicję kolumny. Możesz modyfikować typ danych kolumny, wartość domyślną, ograniczenie kolumny, wyrażenie kolumny (dla kolumn wirtualnych) i szyfrowanie kolumny.

Możesz zwiększyć długość istniejącej kolumny lub ją zmniejszyć, jeśli wszystkie istniejące dane spełniają nową długość. Możesz zmienić kolumnę z semantyki bajtowej na semantykę CHAR lub odwrotnie. Musisz ustawić parametr inicjalizacji BLANK_TRIMMING = TRUE, aby zmniejszyć długość niepustej kolumny CHAR.

Jeśli modyfikujesz tabelę, aby zwiększyć długość kolumny typu danych CHAR, pamiętaj, że może to być czasochłonna operacja i może wymagać znacznej dodatkowej pamięci, zwłaszcza jeśli tabela zawiera wiele wierszy. Wynika to z tego, że wartość CHAR w każdym wierszu musi być wypełniona pustymi polami, aby spełnić nową długość kolumny.

Dokumentacja języka Oracle SQL zawiera znacznie więcej szczegółów, w tym:

Możesz zmienić typ danych dowolnej kolumny, jeśli wszystkie wiersze kolumny zawierają wartości null. Jeśli jednak zmienisz typ danych kolumny w tabeli kontenera widoku zmaterializowanego, baza danych Oracle unieważni odpowiedni widok zmaterializowany.

Zawsze możesz zwiększyć rozmiar znaku lub surowej kolumny lub dokładność kolumny numerycznej, niezależnie od tego, czy wszystkie wiersze zawierają wartości null. Można zmniejszyć rozmiar typu danych kolumny, o ile zmiana nie wymaga modyfikacji danych. Baza danych skanuje istniejące dane i zwraca błąd, jeśli dane przekraczają nowy limit długości.

Możesz zmienić kolumnę DATA na TIMESTAMP lub TIMESTAMP Z LOKALNĄ STREFĄ CZASOWĄ. Możesz zmodyfikować dowolny TIMESTAMP Z LOKALNĄ STREFĄ CZASOWĄ w kolumnie DATA.

Jeśli tabela jest pusta, możesz zwiększyć lub zmniejszyć pole wiodące lub ułamkową drugą wartość kolumny datetime lub interwału. Jeśli tabela nie jest pusta, można zwiększyć tylko pole wiodące lub ułamek sekundy w kolumnie daty i godziny lub przedziału.

W przypadku kolumn CHAR i VARCHAR2 można zmienić semantykę długości, określając CHAR (aby wskazać semantykę znaków dla kolumny, która została pierwotnie określona w bajtach) lub BYTE (aby wskazać semantykę bajtów dla kolumny, która została pierwotnie określona w znakach). Aby poznać semantykę długości istniejących kolumn, przeprowadź zapytanie do kolumny CHAR_USED w widoku słownika danych ALL_, USER_ lub DBA_TAB_COLUMNS.

W powyższej dokumentacji znajdują się dodatkowe informacje i ograniczenia. Oto demonstracja próby zmniejszenia precyzji kolumny Numer i zmniejszenia długości Varchar2. Możesz wypróbować inne zmiany, aby wiedzieć, co się stanie.

--Setup.
DROP TABLE FOO;
CREATE TABLE FOO (BAR Number, BAR2 VARCHAR2(300));
INSERT INTO FOO (SELECT Level, RPAD(to_char(Level),10*Level,to_char(Level)) 
   FROM DUAL CONNECT BY Level <=20);
COMMIT;
SELECT * FROM FOO;

--Reduce Number to Number(10).
ALTER TABLE FOO MODIFY (BAR NUMBER (10));

--Reduce Varchar2(300) to Varchar2(100) (data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100));

--Reduce Varchar2(300) to Varchar2(200) (no data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(200));

Instrukcje alter mają następujące dane wyjściowe:

ALTER TABLE FOO MODIFY (BAR NUMBER (10))
Error report:
SQL Error: ORA-01440: column to be modified must be empty to decrease precision or scale
01440. 00000 -  "column to be modified must be empty to decrease precision or scale"

ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100))
Error report:
SQL Error: ORA-01441: cannot decrease column length because some value is too big
01441. 00000 -  "cannot decrease column length because some value is too big"

table FOO altered.

Zmniejsz precyzję, tworząc nową kolumnę.

ALTER TABLE FOO ADD (BAR3 NUMBER(10));
UPDATE FOO SET Bar3 = Bar;
ALTER TABLE FOO DROP COLUMN BAR;
ALTER TABLE FOO RENAME COLUMN BAR3 TO BAR;
Leigh Riffel
źródło
Wniosek jest taki: jeśli chcesz zmniejszyć precyzję lub skalę kolumny i zachować takie rzeczy, jak indeksy, klucze itp. Jedynym sposobem na to jest skopiowanie tabeli, obcięcie jej, zmiana typów, skopiowanie danych z powrotem i upuszczenie stół tymczasowy. Nie ma szybszego, bardziej eleganckiego sposobu?
mnowotka,
1
Cóż, możesz utworzyć nową kolumnę, skopiować dane, ponownie utworzyć indeks, upuścić starą kolumnę i zmienić nazwę nowej. Możesz także użyć DBMS_REDEFINITION lub utworzyć nową tabelę, skopiować dane, upuścić starą tabelę i zmienić jej nazwę na nową. Możesz też wyeksportować tabelę, upuścić ją, ponownie utworzyć z nową definicją i zaimportować dane. Istnieje wiele sposobów, aby to zrobić, ale szybsza / bardziej elegancka to decyzja, którą musisz podjąć.
Leigh Riffel,
Prawdopodobnie możesz także utworzyć nową kolumnę, skopiować do niej dane, ustawić starą kolumnę na null, zmodyfikować jej długość, skopiować dane z nowej kolumny z powrotem do zmienionej starej kolumny i upuścić nową kolumnę. A wszystko to dlatego, że oracle nie pozwala na redukcję kolumn numerycznych, nawet jeśli dane by pasowały. 8- {
Hans-Peter Störr