Zmień typ pola varchar na integer: „nie można rzutować automatycznie na typ integer”


154

Mam małą tabelkę i pewne pole zawiera typ „ zmienny znak ”. Próbuję zmienić to na „ Integer ”, ale wyświetla błąd, że przesyłanie nie jest możliwe.

Czy istnieje sposób na obejście tego, czy powinienem po prostu utworzyć inną tabelę i wprowadzić do niej rekordy za pomocą zapytania.

Pole zawiera tylko wartości całkowite.


Jakiego rodzaju ALTER TABLE wypróbowałeś i jaki był konkretny komunikat o błędzie?
mu jest za krótkie

@muistooshort Próbowałem użyć alter z phppgadmin. Wybrano kolumnę i próbowano wprowadzić nowy typ pola. Błąd jest następujący:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols

3
Pierwsza to kopia zapasowa tabeli. Następnie możesz utworzyć kolejną kolumnę (powiedzmy field2) typu całkowitego w tej samej tabeli. Wybierz rzutowanie na wartość całkowitą z pola 1 na pole 2. Następnie zmień nazwę kolumny.
Igor

@Igor ale nowa kolumna wypada na koniec tabeli, prawda? Czy nie mogę mieć tego w tej samej pozycji?
itsols

2
@itsols Dbanie o pozycje kolumn jest zwykle oznaką niepewnego projektu aplikacji. Prawie zawsze chcesz używać jawnie nazwanych kolumn i SELECTlist, a nie polegać na pozycjach porządkowych kolumn. To powiedziawszy, podejście podane w odpowiedziach zachowa pozycję kolumny.
Craig Ringer

Odpowiedzi:


264

Nie ma niejawnego (automatycznego) rzutowania z textlub varchardo integer(tj. Nie można przekazać a varchardo funkcji oczekującej integerlub przypisanej varcharpola do integerjedynki), więc należy określić jawne rzutowanie za pomocą ALTER TABLE ... ALTER COLUMN ... TYPE. .. UŻYWANIE :

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (col_name::integer);

Zauważ, że możesz mieć spacje w polach tekstowych; w takim przypadku użyj:

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (trim(col_name)::integer);

aby usunąć odstępy przed konwersją.

Powinno to wynikać z komunikatu o błędzie, jeśli polecenie zostało uruchomione psql, ale możliwe, że PgAdmin-III nie pokazuje pełnego błędu. Oto, co się stanie, jeśli przetestuję go w psqlPostgreSQL 9.2:

=> CREATE TABLE test( x varchar );
CREATE TABLE
=> insert into test(x) values ('14'), (' 42  ');
INSERT 0 2
=> ALTER TABLE test ALTER COLUMN x TYPE integer;
ERROR:  column "x" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion. 
=> ALTER TABLE test ALTER COLUMN x TYPE integer USING (trim(x)::integer);
ALTER TABLE        

Dzięki @muistooshort za dodanie USINGlinku.

Zobacz także to powiązane pytanie ; chodzi o migracje Railsów, ale przyczyna jest taka sama i odpowiedź ma zastosowanie.

Jeśli błąd nadal występuje, może to być związane nie z wartościami kolumn, ale indeksy w tej kolumnie lub wartości domyślne kolumny mogą zakończyć się niepowodzeniem. Indeksy należy usunąć przed ALTER COLUMN i ponownie utworzyć po. Wartości domyślne należy odpowiednio zmienić.


Dziękuję Ci za poświęcenie czasu. Ale nie wydaje mi się, żeby to działało. Wypróbowałem linię ALTER i wyświetla mi się komunikat o błędzie „Błąd składni w pobliżu używania”
itsols

Moje oświadczenie: ALTER TABLE "tblMenus" ALTER COLUMN "MID" USING (trim ("MID") :: integer);
itsols

1
@itsols Całkowicie mój błąd; Poprawiłem to tak, jak zobaczyłem twój komentarz. Zobacz poprawione. To było słuszne w kodzie demonstracyjnym, ale nie był ogólnym przykładem na początku.
Craig Ringer

Stukrotne dzięki! Ta odpowiedź zaoszczędziła mi wielu kłopotów i czasu. Zastanawiam się, dlaczego niether phppgadmin ani pgadmin mają to jako funkcję ...
itsols

@itsols Większość podstawowego zespołu nie jest zainteresowana PgAdmin i niewielu z nich go używa. Ma pewne irytujące brodawki użyteczności i ograniczenia funkcjonalności. To tylko jeden z wielu z nich. Ponieważ niewielu ekspertów używa PgAdmin, nie są oni tak zmotywowani do naprawiania rzeczy, które mogłyby ich denerwować. Sam go nie używam, ponieważ znajduję psqldużo szybciej i łatwiej. Niedawno napisałem rant o użyteczności PgAdmina w zakresie tworzenia kopii zapasowych i przywracania: blog.ringerc.id.au/2012/05/...
Craig Ringer

70

to działało dla mnie.

zmień kolumnę varchar na int

change_column :table_name, :column_name, :integer

dostał:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

chnged to

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

czy wykonałeś to ćwiczenie z danymi i czy Twoje dane były nienaruszone?
itsols

3
o ile to, co jest w kolumnie, jest liczbą całkowitą, tak
bibangamba

Ze mną to nie działa. Używam Ruby 2.2.3 z szynami 4.2.3
Thinh D. Bui

@ ThinhD.Bui - Works for me, 2.3.0, rails 4.2.6
Philip

1
Uważaj również na wartości domyślne
Francisco Quintero

17

Możesz to zrobić tak:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

lub spróbuj tego:

change_column :table_name, :column_name, :integer, using: 'column_name::integer'

Jeśli chcesz dowiedzieć się więcej na ten temat, przeczytaj ten artykuł: https://kolosek.com/rails-change-database-column


8

Spróbuj tego, na pewno zadziała.

Pisząc migracje Railsów, aby przekonwertować kolumnę łańcuchową na liczbę całkowitą, zwykle powiesz:

change_column :table_name, :column_name, :integer

Jednak PostgreSQL będzie narzekać:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

„Wskazówka” w zasadzie mówi ci, że musisz potwierdzić, że chcesz, aby tak się stało i jak dane mają być konwertowane. Po prostu powiedz to podczas migracji:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

Powyższe będzie naśladować to, co znasz z innych adapterów baz danych. Jeśli masz dane nieliczbowe, wyniki mogą być nieoczekiwane (ale mimo wszystko konwertujesz na liczbę całkowitą).


Chciałem tylko dodać jeszcze jeden punkt, uważaj na change_column. jest nieodwracalne. Sugeruję użycie w migracji w górę iw dół, aby było to odwracalne.
Mukesh Kumar Gupta

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""zdarza się błąd
Shaig Khaligli

6

Mam ten sam problem. Potem zdałem sobie sprawę, że mam domyślną wartość ciągu dla kolumny, którą próbowałem zmienić. Usunięcie wartości domyślnej sprawiło, że błąd zniknął :)


Problemem mogą być również istniejące indeksy w tej kolumnie. Należy je upuścić przed ALTER i odtworzyć po.
Envek

1

Jeśli przypadkowo zmieszałeś liczby całkowite z danymi tekstowymi lub nie, powinieneś najpierw wykonać poniższe polecenie update (jeśli nie powyżej, zmiana tabeli nie powiedzie się):

UPDATE the_table SET col_name = replace(col_name, 'some_string', '');

3
Lepiej byłoby zrobić coś takiego, regexp_replace(col_name, '[^0-9.]','','g')jeśli próbujesz usunąć niechciane znaki i spacje. Że trzeba coś nieco bardziej wyrafinowane, jeśli chcesz zachować NaNi Infi 10E42notacji naukowej, choć.
Craig Ringer,

1

Jeśli pracujesz na środowisku programistycznym (lub na środowisku produkcyjnym, może to być kopia zapasowa danych), najpierw wyczyść dane z pola DB lub ustaw wartość na 0.

UPDATE table_mame SET field_name= 0;

Następnie, aby uruchomić poniższe zapytanie, a po pomyślnym uruchomieniu zapytania, do schematu migracji, a następnie uruchom skrypt migracji.

ALTER TABLE table_mame ALTER COLUMN field_name TYPE numeric(10,0) USING field_name::numeric;

Myślę, że to ci pomoże.


1

Miałem ten sam problem. Zacząłem resetować domyślne ustawienia kolumny.

change_column :users, :column_name, :boolean, default: nil
change_column :users, :column_name, :integer, using: 'column_name::integer', default: 0, null: false
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.