Jak zmienić typ danych kolumny ze znakowego na numeryczny w PostgreSQL 8.4

136

Używam następującego zapytania:

ALTER TABLE presales ALTER COLUMN code TYPE numeric(10,0); 

aby zmienić typ danych kolumny z character(20)na, numeric(10,0)ale otrzymuję błąd:

kolumna „kod” nie może być rzutowana na typ liczbowy

user728630
źródło

Odpowiedzi:

240

Możesz spróbować użyć USING:

Opcjonalna USINGklauzula określa, jak obliczyć nową wartość kolumny na podstawie starej; jeśli zostanie pominięty, domyślna konwersja jest taka sama, jak rzutowanie przypisania ze starego typu danych na nowy. USINGKlauzula musi być zapewnione, jeśli nie ma niejawny lub cesja odlewane ze starego do nowego typu.

Więc to może zadziałać (w zależności od twoich danych):

alter table presales alter column code type numeric(10,0) using code::numeric;
-- Or if you prefer standard casting...
alter table presales alter column code type numeric(10,0) using cast(code as numeric);

To się nie powiedzie, jeśli masz coś code, czego nie można rzucić na numeryczne; jeśli USING nie powiedzie się, będziesz musiał ręcznie wyczyścić dane nienumeryczne przed zmianą typu kolumny.

mu jest za krótkie
źródło
ta kolumna jest używana jako klucz obcy w innej tabeli, myślę, że będę musiał zmienić również typ danych?
user728630
2
@ user728630: Będziesz musiał usunąć FK, zmienić obie kolumny, a następnie dodać ponownie FK. Masz testową bazę danych do zabawy i kopię zapasową produkcyjnej bazy danych, prawda?
mu jest za krótkie
Usunąłem ograniczenie klucza obcego, zmieniłem typ danych, ale nie mogłem dodać FK. Pojawia się następujący błąd BŁĄD: wstawianie lub aktualizowanie tabeli „faktury” narusza ograniczenie klucza obcego „faktura_presale_fk” DETAIL: Klucz (sprzedaż, cpf_cnpj) = (4,05943560000101) nie występuje w tabeli „przedsprzedaż”.
user728630
2
@funwhilelost To jest typowa obsada . Połączone dokumenty ALTER TABLE zawierają informacje o tym, czego można używać z funkcją USING.
mu jest za krótkie
3
@muistooshort Widzę z dokumentów, że to właściwie wyrażenie. To ma więcej sensu. Ten typ obsady zaskoczył mnie. Skończyło się naTYPE varchar(255) USING (substring(formertextcolumn from 1 for 255))
funwhilelost
7

Jeśli twoja VARCHARkolumna zawiera puste łańcuchy (które nie są takie same jak NULLdla PostgreSQL, jak być może pamiętasz), będziesz musiał użyć czegoś w linii poniżej, aby ustawić wartość domyślną:

ALTER TABLE presales ALTER COLUMN code TYPE NUMERIC(10,0)
            USING COALESCE(NULLIF(code, '')::NUMERIC, 0);

(znalezione za pomocą tej odpowiedzi )

Patru
źródło