1

Temat: [SQL] Zmiana typu kolumny

Szperałem na Forum, ale niestety nie znalazłem rozwiązania (być może źle szukałem). Próbuję zmienić typ pola w tabeli. Na początku miałem zaćmienie i zrobiłem pole typu "character varying" zamiast "integer", dla danych, które będą liczbowe.

Zauważyłem to dopiero dzisiaj i szybko chciałem to naprawić, a tu zonk :-) Próbowałem zrobić coś takiego:

ALTER TABLE tabela ADD COLUMN kolumna_temp INTEGER DEFAULT 0;
UPDATE tabela SET kolumna_temp = kolumna;

A później po prostu usunąć "kolumna" i zmienić nazwę "kolumna_temp" na "kolumna". Ale Postgres krzyczy, że "kolumna" jest typu "character varying" i nie zrobi UPDATE do kolumny typu "integer". Niby poprawnie, ale jak to obejść?

Próbowałem dodawać "::integer", ale to nic nie zmienia.

Cały problem wynika z tego, że w polu "kolumna", mam zapisany "wzrost" i gdy próbuję zrobić zapytanie typu:

SELECT * FROM tabela WHERE kolumna BETWEEN 150 AND 180

Wyrzuca błąd, co w sumie oczywiste, gdy typ kolumny jest zły.

Jak zmienić ten skubany typ kolumny? :-)

2

Odp: [SQL] Zmiana typu kolumny

Typ możesz zmienić bezprośrednio przez alter'a np.:

ALTER TABLE tabela ALTER COLUMN kolumna TYPE integer USING NULL;

Jeśli w kolumnie kolumna znajdują się jakieś wpisy nie-liczbowe, to using na końcu je skasuje (zamiast NULL można podać dowolną wartość akceptowalną dla typu integer np. 0), ew. można zrobić wcześniej Delete na takich wpisach. Wartość domyślną można nadać/zdjąć także przez alter'a np.:

ALTER TABLE tabela ALTER COLUMN kolumna SET DEFAULT 0;
ALTER TABLE
\d tabela
                          Table "public.tabela"
 Column  |  Type   |                      Modifiers                      
---------+---------+-----------------------------------------------------
 id      | integer | not null default nextval('tabela_id_seq'::regclass)
 kolumna | integer | default 0
Indexes:
    "tabela_pkey" PRIMARY KEY, btree (id)

ALTER TABLE tabela ALTER COLUMN kolumna DROP DEFAULT;
ALTER TABLE
\d tabela
                          Table "public.tabela"
 Column  |  Type   |                      Modifiers                      
---------+---------+-----------------------------------------------------
 id      | integer | not null default nextval('tabela_id_seq'::regclass)
 kolumna | integer | 
Indexes:
    "tabela_pkey" PRIMARY KEY, btree (id)

3

Odp: [SQL] Zmiana typu kolumny

Tylko, że to skasuje mi dane w polu "kolumna", a to zdecydowanie nie wchodzi w grę :-)

EDIT:

Ewentualnie mogę to zrobić przez skrypt PHP, jeżeli w Postgresie nie ma takiej możliwości. Chociaż wolałbym w SQL.

Ostatnio edytowany przez Shavei (2012-02-16 14:24:24)

4

Odp: [SQL] Zmiana typu kolumny

ALTER TABLE tabela
    ALTER COLUMN kolumna TYPE integer
    USING int4(kolumna);

lub zamiast int4() dodaj sobie taką funkcję

CREATE OR REPLACE FUNCTION pc_chartoint(chartoconvert character varying)
  RETURNS integer AS
$BODY$
SELECT CASE WHEN trim($1) SIMILAR TO '[0-9]+' 
        THEN CAST(trim($1) AS integer) 
    ELSE NULL END;

$BODY$
  LANGUAGE 'sql' IMMUTABLE STRICT;

i wtedy podajesz ją w using zamiast int4(). W przypadku jeśli w tabeli są jakieś dane nieintegerowe, to zamieni je na null. Czy jest Ci to potrzebne i oczekujesz takiego zachowania to nie wiem.

somewhere around nothing

5

Odp: [SQL] Zmiana typu kolumny

Dziękuję Ci bardzo, właśnie o funkcję "pc_chartoint" się wszystko rozchodziło :-)

6

Odp: [SQL] Zmiana typu kolumny

mam podobny problem, ale nie wiem jak "zagniezdzic" powyzsza funkcje...
wyskakuje blad
"BŁĄD:  błąd składni w lub blisko "CREATE"
LINE 3:     USING CREATE OR REPLACE FUNCTION pc_chartoint(chartoconv..."

pomocy:)

7

Odp: [SQL] Zmiana typu kolumny

Myślę że chodziło o podstawienie

... USING pc_chartoint(..)

Funkcja musi być wczesniej utworzona.

8

Odp: [SQL] Zmiana typu kolumny

puszczam ta funkcje i pozniej cos takiego, ktore niestety czysci mi dane z kolumny....
ALTER TABLE tabela
    ALTER COLUMN kolumna TYPE integer
    USING pc_chartoint(kolumna);

9

Odp: [SQL] Zmiana typu kolumny

dla potomnych:)

ALTER TABLE tabela
     ALTER COLUMN kolumna TYPE integer
     USING CAST(kolumna AS integer);