Cómo cambiar el tipo de datos de columna de carácter a numérico en PostgreSQL 8.4

136

Estoy usando la siguiente consulta:

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

para cambiar el tipo de datos de una columna de character(20)a numeric(10,0)pero recibo el error:

la columna "código" no se puede convertir a tipo numérico

usuario728630
fuente

Respuestas:

241

Puedes intentar usar USING:

La USINGcláusula opcional especifica cómo calcular el nuevo valor de columna a partir del anterior; si se omite, la conversión predeterminada es la misma que una asignación emitida del tipo de datos antiguo a nuevo. Se USINGdebe proporcionar una cláusula si no hay conversión implícita o de asignación del tipo antiguo al nuevo.

Entonces esto podría funcionar (dependiendo de sus datos):

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);

Esto fallará si tiene algo codeque no se puede convertir a numérico; Si el uso falla, tendrá que limpiar los datos no numéricos a mano antes de cambiar el tipo de columna.

mu es demasiado corto
fuente
esta columna se usa como una clave foránea en otra tabla, supongo que también tendré que cambiar el tipo de datos.
user728630
2
@ user728630: Tendrá que soltar el FK, cambiar ambas columnas y luego volver a agregar el FK. Tienes una base de datos de prueba para jugar y una copia de seguridad de la base de datos de producción, ¿verdad?
mu es demasiado corto el
Eliminé la restricción de clave externa, cambié el tipo de datos pero después de eso no pude agregar el FK. Obteniendo el siguiente error ERROR: insertar o actualizar en la tabla "facturas" viola la restricción de clave externa "invoice_presale_fk" DETALLE: La clave (sale, cpf_cnpj) = (4,05943560000101) no está presente en la tabla "preventa".
user728630
2
@funwhilelost Ese es un tipo de reparto . Los documentos ALTER TABLE vinculados cubren lo que puede usar con el USO.
mu es demasiado corto
3
@muistooshort Veo por los documentos que en realidad es una expresión. Eso tiene más sentido. El tipo de yeso me tomó por sorpresa. Terminé conTYPE varchar(255) USING (substring(formertextcolumn from 1 for 255))
funwhilelost
7

Si su VARCHARcolumna contiene cadenas vacías (que no son las mismas que NULLpara PostgreSQL como podría recordar), tendrá que usar algo en la línea de lo siguiente para establecer un valor predeterminado:

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

(encontrado con la ayuda de esta respuesta )

Patru
fuente