Comment changer le type de données de colonne de caractère à numérique dans PostgreSQL 8.4

136

J'utilise la requête suivante:

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

pour changer le type de données d'une colonne de character(20)à numeric(10,0)mais j'obtiens l'erreur:

La colonne "code" ne peut pas être convertie en type numérique

user728630
la source

Réponses:

241

Vous pouvez essayer d'utiliser USING:

La USINGclause facultative spécifie comment calculer la nouvelle valeur de colonne à partir de l'ancienne; s'il est omis, la conversion par défaut est la même qu'une affectation convertie de l'ancien type de données en nouveau. Une USINGclause doit être fournie s'il n'y a pas de conversion implicite ou d'affectation de l'ancien au nouveau type.

Cela pourrait donc fonctionner (en fonction de vos données):

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

Cela échouera si vous avez quelque chose codequi ne peut pas être converti en numérique; si l'utilisation échoue, vous devrez nettoyer les données non numériques à la main avant de changer le type de colonne.

mu est trop court
la source
cette colonne est utilisée comme clé étrangère dans une autre table, je suppose que je devrai changer le type de données de cela aussi?
user728630
2
@ user728630: Vous devrez supprimer le FK, changer les deux colonnes, puis rajouter le FK. Vous avez une base de données de test avec laquelle jouer et une sauvegarde de la base de données de production, non?
mu est trop court
J'ai supprimé la contrainte de clé étrangère, changé le type de données mais après cela, je n'ai pas pu ajouter le FK. Obtenir l'erreur d'erreur suivante ERREUR: l'insertion ou la mise à jour sur la table "factures" viole la contrainte de clé étrangère "facture_presale_fk" DÉTAIL: La clé (vente, cpf_cnpj) = (4,05943560000101) n'est pas présente dans la table "préventes".
user728630
2
@funwhilelost C'est un casting de type . Les documents ALTER TABLE liés couvrent ce que vous pouvez utiliser avec USING.
mu est trop court
3
@muistooshort Je vois dans la documentation que c'est en fait une expression. Cela a plus de sens. Le casting du type m'a pris au dépourvu. J'ai fini avecTYPE varchar(255) USING (substring(formertextcolumn from 1 for 255))
funwhilelost
7

Si votre VARCHARcolonne contient des chaînes vides (qui ne sont pas les mêmes que NULLpour PostgreSQL, comme vous vous en souvenez peut-être), vous devrez utiliser quelque chose dans la ligne suivante pour définir une valeur par défaut:

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

(trouvé à l'aide de cette réponse )

Patru
la source