Cambia il tipo di campo varchar in intero: "impossibile eseguire il cast automatico per digitare un numero intero"


154

Ho una piccola tabella e un determinato campo contiene il tipo " carattere variabile ". Sto provando a cambiarlo in " Numero intero ", ma viene visualizzato un errore per cui il casting non è possibile.

C'è un modo per aggirare questo problema o dovrei semplicemente creare un'altra tabella e inserire i record in essa usando una query.

Il campo contiene solo valori interi.


Quale specifica ALTER TABLE hai provato e qual è stato il messaggio di errore specifico?
mu è troppo corto il

@muistooshort Ho provato ad usare alter da phppgadmin. Selezionato la colonna e provato a inserire il nuovo tipo di campo. L'errore è:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols

3
Il primo è il backup della tabella. Quindi è possibile creare un'altra colonna (ad esempio field2) di tipo intero nella stessa tabella. Seleziona il cast al valore intero del campo1 nel campo2. Quindi rinominare la colonna.
Igor

@Igor ma la nuova colonna cade alla fine della tabella giusto? Non posso averlo nella stessa posizione?
itsols

2
@itsols Preoccuparsi delle posizioni delle colonne è di solito un segno del design dell'applicazione iffy. Si desidera quasi sempre utilizzare colonne ed SELECTelenchi con nomi espliciti , senza fare affidamento sulle posizioni ordinali delle colonne. Detto questo, l'approccio indicato nelle risposte manterrà la posizione della colonna.
Craig Ringer,

Risposte:


264

Non esiste un cast (automatico) implicito da texto varchara integer(ovvero non è possibile passare varchara una funzione in attesa integero assegnare un varcharcampo a integeruno), quindi è necessario specificare un cast esplicito utilizzando ALTER TABLE ... ALTER COLUMN ... TYPE. .. USANDO :

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

Nota che potresti avere spazi bianchi nei tuoi campi di testo; in tal caso, utilizzare:

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

rimuovere gli spazi bianchi prima della conversione.

Questo shoud è stato ovvio da un messaggio di errore se il comando è stato eseguito psql, ma è possibile che PgAdmin-III non ti mostri l'errore completo. Ecco cosa succede se lo collaudo psqlsu PostgreSQL 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        

Grazie @muistooshort per aver aggiunto il USINGlink.

Vedi anche questa domanda correlata ; riguarda le migrazioni di Rails, ma la causa sottostante è la stessa e si applica la risposta.

Se l'errore persiste, è possibile che non sia correlato ai valori di colonna, ma gli indici su questa colonna o i valori predefiniti di colonna potrebbero non eseguire il typecast. Gli indici devono essere eliminati prima di ALTER COLUMN e ricreati dopo. I valori predefiniti devono essere modificati in modo appropriato.


Grazie per aver dedicato del tempo. Ma non riesco a farlo funzionare. Ho provato la tua linea ALTER e mi dà un errore "Errore di sintassi vicino all'utilizzo"
itsols

La mia dichiarazione: ALTER TABLE "tblMenus" ALTER COLUMN "MID" USING (trim ("MID") :: integer);
itsols

1
@itsols Interamente il mio errore; L'ho corretto proprio come ho visto il tuo commento. Vedi rivisto. Era proprio nel codice demo, ma non nell'esempio generico all'inizio.
Craig Ringer,

Grazie mille! Questa risposta mi ha fatto risparmiare un sacco di problemi e tempo. Mi chiedo perché niether phppgadmin né pgadmin abbiano questo come caratteristica ...
itsols

@itsols La maggior parte del core team non è così interessato a PgAdmin, e pochi lo usano. Ha alcune fastidiose verruche di usabilità e limiti di funzionalità. Questo è solo uno dei tanti. Poiché pochi esperti usano PgAdmin, non sono così motivati ​​a risolvere le cose che li infastidirebbero. Non lo uso da solo, perché trovo psqlmolto più veloce e più facile. Ho scritto un po 'di rabbia sull'usabilità di PgAdmin per quanto riguarda il backup e il ripristino qualche tempo fa: blog.ringerc.id.au/2012/05/…
Craig Ringer

70

questo ha funzionato per me.

cambia la colonna varchar in int

change_column :table_name, :column_name, :integer

avuto:

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

ribattuto a

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

hai provato questo esercizio con i dati ed erano intatti?
itsols

3
purché ciò che è nella colonna sia un numero intero, sì
bibangamba

Non funziona con me. Sto usando ruby ​​2.2.3 con binari 4.2.3
Thinh D. Bui

@ ThinhD.Bui - Funziona per me, 2.3.0, rotaie 4.2.6
Philip

1
Fai attenzione anche alle impostazioni predefinite
Francisco Quintero,

17

Puoi farlo come:

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

o prova questo:

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

Se sei interessato a saperne di più su questo argomento leggi questo articolo: https://kolosek.com/rails-change-database-column


8

Prova questo, funzionerà di sicuro.

Quando scrivi le migrazioni di Rails per convertire una colonna stringa in un numero intero, di solito dovresti dire:

change_column :table_name, :column_name, :integer

Tuttavia, PostgreSQL si lamenterà:

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

Il "suggerimento" in sostanza ti dice che devi confermare che vuoi che ciò accada e come devono essere convertiti i dati. Dì questo nella tua migrazione:

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

Quanto sopra imiterà ciò che sai dagli altri adattatori di database. Se disponi di dati non numerici, i risultati potrebbero essere inattesi (ma dopo tutto stai convertendo in un numero intero).


Volevo solo aggiungere un altro punto che, stai attento con change_column. è irreversibile. Suggerisco di usare su e giù nella migrazione per renderlo reversibile.
Mukesh Kumar Gupta,

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""si verifica un errore
Shaig Khaligli

6

Ho avuto lo stesso problema. Di quanto ho capito avevo un valore di stringa predefinito per la colonna che stavo cercando di modificare. La rimozione del valore predefinito ha fatto scomparire l'errore :)


Anche gli indici esistenti su questa colonna potrebbero essere un problema. Devono essere lasciati cadere prima di ALTER e ricreati dopo.
Envek,

1

Se hai mescolato accidentalmente o no numeri interi con dati di testo, dovresti prima eseguire il comando di aggiornamento sotto (se non sopra la tabella di modifica fallirà):

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

3
Faresti meglio con qualcosa di simile regexp_replace(col_name, '[^0-9.]','','g')se stai cercando di spogliare personaggi indesiderati e spazi bianchi. Avreste bisogno di qualcosa di un po 'più sofisticato, se si desidera mantenere NaNe Infe 10E42notazione scientifica, però.
Craig Ringer,

1

Se si sta lavorando su un ambiente di sviluppo (o su ambiente di produzione, potrebbe essere il backup dei dati), quindi per prima cosa cancellare i dati dal campo DB o impostare il valore su 0.

UPDATE table_mame SET field_name= 0;

Successivamente, per eseguire la query seguente e dopo aver eseguito correttamente la query, sulla schemamigrazione e successivamente eseguire lo script di migrazione.

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

Penso che ti aiuterà.


0

Ho avuto lo stesso problema. Ho iniziato a ripristinare il valore predefinito della colonna.

change_column :users, :column_name, :boolean, default: nil
change_column :users, :column_name, :integer, using: 'column_name::integer', default: 0, null: false
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.