URL: https://linuxfr.org/forums/programmation-sql/posts/cr%C3%A9er-une-clef-avec-une-fonction Title: Créer une clef avec une fonction Authors: Gyro Gearllose Date: 2007年11月20日T08:58:59+01:00 Tags: postgresql Score: 0 Bonjour, Pour une base de données, j'ai besoin d'identifier un dossier saisi dans une table à l'aide d'un champ qui doit être calculé. Ce champ, qui sera la clef primaire de la table doit se présenter sous la forme : yyyymmdd-num-X. Avec : - yyyymmdd la date du jour, - num un numéro d'ordre de saisie et - X une clef calculée sur un modulo 26 du total précédent. Exemple : 20071119-01-F Petit détail qui a son importance : cette base de données, comme toutes les autres, finalement, tourne sous postgresql version 8.2.5. Au point où j'en suis, voici comment j'ai procédé : J'ai créé une table comme suit :
create table num_dos ( dat_cur varchar(8), num_ord integer);Et une fonction qui utilise cette table :
create or replace function num_dos() returns varchar as $$ declare cur_rec record; begin select into cur_rec * from num_dos limit 1; if (not found) then insert into num_dos values (to_char(now(), 'yyyymmdd'), 1); else if (cur_rec.dat_cur != to_char(now(), 'yyyymmdd')) then update num_dos set dat_cur = to_char(now(), 'yyyymmdd'), num_ord = 1; else update num_dos set num_ord = num_ord+1; end if; end if; select into cur_rec * from num_dos limit 1; return (cur_rec.dat_cur || '-' || trim(to_char(cur_rec.num_ord, '00')) || '-' || chr(65 + ( cur_rec.dat_cur || cur_rec.num_ord)::integer % 26)); end; $$ language plpgsql;Mon idée, partant de ça, est de créer une table dossier ainsi :
create table dos ( num_dos varchar(13) default num_dos() primary key, ...Mes questions à propos de cette façon de faire : - Comment gérer les cas où l'ajout dans la table dos échoue ? Parce que dans ce cas, la fonction num_dos() aura été appelée pour rien, et le numéro d'ordre sera incrémenté pour rien. Du coup, je risque d'avoir des trous dans mes numéros d'ordre, ce que j'aimerai éviter autant que possible. A moins que le fait d'encadrer ça dans une transaction suffise à éviter la mise à jour de la table num_dos en cas de rollback ? Y a-t-il une autre façon de faire la même chose qui soit plus efficace ? J'ai bien pensé à créer une fonction similaire qui, au lieu de se baser sur une table annexe, se base sur la table dos, en parcourant tous les champs num_dos commençant par la date du jour, et à ajouter 1 au dernier numéro trouvé, mais ça me parraissait lourd, d'autant que cette table risque de contenir beaucoup d'enregistrements. Qu'en pensez-vous ? Avez-vous d'autres idées pour gérer ça ? Passer par une "rule" sur la table num_dos ? Passer par une nouveau type ? Merci pour vos idées par avance, je poursuis mes essais avec cette structure en attendant d'éventuels avis sur la question.