Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Je viens de me rendre compte qu'une contrainte d'unicité que j'avais établie pour une table ne fonctionne pas (ou plutôt j'imagine que j'ai dû mal la faire).
Je m'en suis rendu compte parce que j'ai créé par erreur un anc_lot qui existait déjà (sauf pour le id_anc_lot et le code_circ qui étaient différents mais vu la contrainte code_cad_code_ds_no_lot_key selon moi ça n'aurait pas dû passer) et c'est passé.
Qu'est-ce que j'ai mal fait (et donc comment dois-je le corriger ?)
Merci.
Le SQL de ma table est :
-- Table: greffe.anc_lots
-- DROP TABLE greffe.anc_lots;
CREATE TABLE greffe.anc_lots
(
id_anc_lot integer NOT NULL DEFAULT nextval('greffe.anc_lots_id_seq'::regclass),
code_circ smallint NOT NULL,
code_cad integer NOT NULL,
code_ds character varying(255) COLLATE pg_catalog."default" NOT NULL,
no_lot character varying(255) COLLATE public."numeric" NOT NULL,
CONSTRAINT anc_lots_pkey PRIMARY KEY (id_anc_lot),
CONSTRAINT code_cad_code_ds_no_lot_key UNIQUE (code_cad, code_ds, no_lot)
)
TABLESPACE pg_default;
ALTER TABLE greffe.anc_lots
OWNER to jm;
GRANT DELETE, INSERT, SELECT, UPDATE ON TABLE greffe.anc_lots TO application_greffe;
GRANT ALL ON TABLE greffe.anc_lots TO jm;
-- Index: anc_lots_code_cad_idx
-- DROP INDEX greffe.anc_lots_code_cad_idx;
CREATE INDEX anc_lots_code_cad_idx
ON greffe.anc_lots USING btree
(code_cad ASC NULLS LAST)
TABLESPACE pg_default;
-- Index: anc_lots_code_circ_idx
-- DROP INDEX greffe.anc_lots_code_circ_idx;
CREATE INDEX anc_lots_code_circ_idx
ON greffe.anc_lots USING btree
(code_circ ASC NULLS LAST)
TABLESPACE pg_default;
-- Index: anc_lots_code_ds_idx
-- DROP INDEX greffe.anc_lots_code_ds_idx;
CREATE INDEX anc_lots_code_ds_idx
ON greffe.anc_lots USING btree
(code_ds COLLATE pg_catalog."default" ASC NULLS LAST)
TABLESPACE pg_default;
-- Index: anc_lots_code_lot_idx
-- DROP INDEX greffe.anc_lots_code_lot_idx;
CREATE INDEX anc_lots_code_lot_idx
ON greffe.anc_lots USING btree
(no_lot COLLATE public."numeric" ASC NULLS LAST)
TABLESPACE pg_default;
Hors ligne
Bonjour,
Avez-vous une erreur si vous faites un REINDEX de cette table ? C'est probablement un problème de mise à jour de glibc / ICU, cf https://wiki.postgresql.org/wiki/Locale_data_changes
Julien.
https://rjuju.github.io/
Hors ligne
Bonjour Julien,
Merci de votre attention et de votre proposition mais non, le réindex n'a donné aucune erreur :
REINDEX
Query returned successfully in 1 secs 161 msec.
Hors ligne
On voit que cette collation non standard intervient dans la contrainte unique:
no_lot character varying(255) COLLATE public."numeric" NOT NULL,
Quelle est la définition de cette collation?
Est-ce qu'une requête SELECT avec un GROUP BY sur les colonnes de la contrainte et HAVING count(*)>1 renvoie effectivement des lignes?
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Bonjour dverite,
J'avais créé cette table avec PgAdmin4 et je n'ai pas remarqué ce collate (et honnêtement je ne sais pas ce que c'est ni à quoi ça sert).
Mon attention attirée, je constate qu'il y en a un sur le code_ds aussi, comme dans beaoucoup de colonnes d'autres tables que j'ai créées avec PgAdmin4.
Est-ce qu'une requête SELECT avec un GROUP BY sur les colonnes de la contrainte et HAVING count(*)>1 renvoie effectivement des lignes?
Dès que je me suis rendu compte qu'il prenait une ligne qu'il n'aurait pas du, j'ai fait la vérification et, une fois cette nouvelle ligne erronée supprimée, il n'y a pas de doublon dans la table.
Comment puis-je enlever ces collate en m'assurant de ne pas perdre de donnée ?
Merci de votre attention et de votre aide.
Dernière modification par Jean-Marc68 (27/04/2023 22:25:29)
Hors ligne
Vous pouvez utiliser
ALTER TABLE nom_table ALTER COLUMN nom_colonne TYPE nom_type COLLATE "default";
Julien.
https://rjuju.github.io/
Hors ligne
Merci de l'info rjuju,
Toutefois quand j'ai posé la question j'étais à la maison (ça me travaille le soir), et arrivé au bureau, en faisant la correction que tu me donnes, je me suis demandé pourquoi cette colonne avait un collate différent des autres (ça ne pouvais pas être venu tout seul). En fouillant dans mes dossiers, j'ai retrouvé que j'ai mis ce collate pour avoir un tri "naturel". Mais vu que ça pose problème, je vais le laisser à défault (de toute manière je suis le seul à travailler dans postgresql. Les autres utilisateurs utilisent des applications qui font appel à PostgreSQL (il faudra "simplement" que je vérifie que les tris se fassent dans les applications et pas dans les appels sql)).
Merci beaucoup à vous deux.
Dernière modification par Jean-Marc68 (28/04/2023 15:04:05)
Hors ligne
La collation influe sur le résultat de la comparaison des chaînes de caractères.
Ici la contrainte d'unicité sur (code_cad, code_ds, no_lot) implique qu'à l'insertion ou MAJ d'une ligne, le moteur vérifie qu'il n'y a pas déjà une valeur pour laquelle il y aurait code_cad=nouveau code_cad ET code_ds=nouveau code ds ET no_lot=nouveau no_lot.
Comme il y a une collation personnalisée affectée à la colonne no_lot, la comparaison no_lot=nouveau no_lot se fait avec cette collation. Sans savoir comment est définie cette collation (ça peut se voir avec select * from pg_collation WHERE collname='numeric') et quelle est la valeur de no_lot qu'il ne reconnait pas comme un doublon alors que c'en serait un, difficile de dire si c'est la faute de la collation.
Surtout dans ce sens là d'ailleurs. Si c'était une valeur différente qui était égale d'après la collation, ce serait plus compréhensible (par exemple abc=ABC pour une collation case-insensitive). Mais deux valeurs réellement identiques à l'octet près dont la collation dit qu'elle sont différentes, là je ne vois pas bien quelle collation pourrait dirait ça. Une autre piste pourrait être plus simplement des caractères invisibles dans les valeurs, avec Unicode ça arrive. Dans ce cas, le fait qu'il y a une collation personnalisée serait une coïncidence.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Les valeurs de cette table proviennent d'une importation d'une ancienne table en Access et effectivement, il y avait bien un caractère en plus dans certaines lignes valeur (je n'ai pas pensé à "trimmer" les champs et après vérification sur les champs code_ds et no_lot (qui sont des string) j'ai effectivement certains endroit où il y a un espace à la fin du champs. Heureusement après vérification il y a seulement 22 doublons dus à cet espace. Je vais donc d'abord régler les doublons (changer l'id dans les tables liées et enlever les lignes qui ont un espace), puis je vais faire une requete update pour supprimer les espaces.
Ça devrait résoudre mon problème.
Merci beaucoup.
Hors ligne
Pages : 1