PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 02/10/2011 14:31:11

cedric a écrit :

bonjour,
je n'ai pas lu tout le fil de discussion. Toutefois, en réponse à l'article:
Construire toute un logique de mise à jour de la valeur d'une séquence me semble complètement inutile et montre le problème de normalisation du schéma SQL prévu.
Si le but est de changer le tri des données, on utilise une colonne spécifique.

Ouep je suis tout à fait d'accord ! Mais bon au cas où, sa peut servir, moi par exemple j'ai un site déjà tout fait et je suis obligé de passé par là wink

#2 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 02/10/2011 02:32:29

J'ai bien étudié tout ce que vous m'avez dit et j'ai rédiger un petit article histoire de pas oublier :

http://hayj.free.fr/index.php?id_slvl=35

Dsl je ne me suis pas encore très bien relu donc il doit y avoir des fautes !

#3 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 19:23:12

Malheureusement le if ne fonctionne pas :

CREATE OR REPLACE FUNCTION updateNextvalTable1()
RETURNS TRIGGER
AS $$
DECLARE
	val integer;
BEGIN
	if(NEW.id = NULL) then
		raise exception 'Vous navez pas mentionné d id dans votre INSERT';
	else
		raise exception 'Vous avez mentionné un id dans votre INSERT';
	end if;
	RETURN NEW;
END; $$ language 'plpgsql';

CREATE TRIGGER TriggerUpdateNextvalTable1
BEFORE INSERT
ON table1
FOR EACH ROW EXECUTE PROCEDURE updateNextvalTable1();

il me renvoie toujours : Vous avez mentionné un id dans votre INSERT.


Il faudrait une instruction du genre :

if(string(NEW.numero1) = "id") then ....

mais je doute que ça existe !

#4 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 19:16:37

rjuju a écrit :

Le probème vient que ton trigger se lance après l'insert, c'est-à-dire une fois que la séquence a fait son travail, et il est alors impossible de différencier les 2 utilisations. Peut-être qu'en faisant le trigger BEFORE INSERT tu peux différencier les 2 cas mais je n'ai jamais testé et je ne peux pas te répondre, même si j'aurais tendance à penser que le new.ID serait à NULL et non pas à 0. Peut-être que Guillaume aura une réponse sure.

Ce n'est vraiment pas bête ce que tu dis, d'ailleurs j'y avait pensé mais je ne me rappel plus ce qui s'est passé, je réessaye et je te tiens au courant.

#5 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 19:13:49

rjuju a écrit :

Effectivement mon premier réflexe serait de te conseiller un autre champ pour gérer la position, pour ne pas mélanger un identifiant de ligne avec une valeur fonctionnelle, ou éviter des problème de propagation de clé étrangères (ON UPDATE CASCADE). A tous hasard est-ce un choix d'ordre subjectif ou y aurait-il une autre zone sur laquelle tu pourrais exercer un tri (date, valeur ...) ?

Ouai tu a raison je devrai prendre un champ position, la prochaine fois je le fera.
Je ne l'ai pas fait car dans mon php, j'envoie des pages html avec les id en id de balise, donc plus facile pour réutiliser l'id de l'élément. Tu me dira que je peux designer mon élément également grâce à la position du fait que ce champs peut être une clef candidate, et oui tu a raison donc j'y penserai la prochaine fois xD

Et non il n'y a pas d'autre zone sur laquelle je pourrai exercer un tri (je n'ai pas bien compris où tu voulais en venir en fait dsl !).

#6 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 19:03:18

ok merci gleu, une dernière question et je te laisse x)

Ce que je voudrais faire, c'est juste savoir dans ma procédure si l'utilisateur écrit
ça : INSERT INTO table1(id,nom) VALUES(2,'blabla1'); -- à ce moment là je devrai mettre à jour last_value
ou ça : INSERT INTO table1(nom) VALUES('blabla1'); -- le serial fait le travail

Cette procédure ressemblerai à ça :

CREATE OR REPLACE FUNCTION updateNextvalTable1()
RETURNS TRIGGER
AS $$
DECLARE
	val integer;
BEGIN
	if(NEW.id > 0) then
		SELECT max(id) INTO val FROM table1;
		val = val + 1;
		EXECUTE 'ALTER SEQUENCE table1_id_seq RESTART WITH ' || val;
	end if;
	RETURN NEW;
END; $$ language 'plpgsql';

CREATE TRIGGER TriggerUpdateNextvalTable1
AFTER INSERT
ON table1
FOR EACH ROW EXECUTE PROCEDURE updateNextvalTable1();

problème : mon if fonctionne dans tout les cas ! Donc last_value se mettra à jour alors qu'il est deja à jour si je tape mon insert sans precisé l'id !

#7 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 18:42:53

rjuju a écrit :

Est-ce dans un soucis de "combler les trous" que tu veux faire un update du champ id ? Car comme le disait Marc vu le nombre de valeur possibles ce n'est vraiment pas nécessaire.

En fait pas vraiment, j'ai pris conscience que "combler les trous" ne servait à rien, par contre ce qu'il m'arrive de faire assez souvent, c'est de modifier l'ordre des lignes. Exemple :

ligneA d'id 1
ligneB d'id 2
ligneC d'id 3

Je veux mettre ligneB en dernière position, alors j'obtiendrai ça :

ligneA d'id 1
ligneC d'id 3
ligneB d'id 4 -- erreur lors du prochain insert car last_value n'est pas à jour

Peut être me conseillera tu de mettre un champ "position integer" mais je trouve ça moins propre !



gleu merci beaucoup ça marche et désolé pour le message d'erreur !
Peut on optimiser les choses en faisant une règle ?

DROP RULE IF EXISTS updateNextvalTable1 ON table1;
CREATE RULE updateNextvalTable1
AS ON UPDATE
TO table1
DO ALSO
(
	ALTER SEQUENCE table1_id_seq RESTART WITH (SELECT max(id) INTO val FROM table1) + 1;
);

Message d'erreur:

ERREUR:  erreur de syntaxe sur ou près de « ALTER »
LINE 34:  ALTER SEQUENCE table1_id_seq RESTART WITH (SELECT max(id) I...

Je crois qu'on ne peut pas mettre ce type de requetes, en plus il risque de ne pas aimé mon +1, je me trompe ?

#8 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 01/10/2011 15:32:17

Merci pour ta réponse Marc, effectivement quelques dizaines de millions d'années à raison de 1000 numéros à la seconde ça fait beaucoup !

Alors, j'ai étudier tout ce que vous m'avez dit depuis hier, et il subsiste un vrai problème :
Je suis d'accord sur le fait qu'il faut utiliser des sequences (serial) pour les id, mais le probleme est que, lorsque l'on fait un update d'un id de la table en question, la variable last_value de la sequence n'est pas mis à jour (voir http://dgriessinger.developpez.com/post … equences/).

Je m'explique avec un exemple :

si on fait

CREATE TABLE table1
(
    id serial primary key,
    nom varchar(255) NOT NULL
);
INSERT INTO table1(nom) VALUES('blabla1'); -- id = 1
UPDATE table1 SET id = 2 where id = 1; on met la première ligne à l'id 2
INSERT INTO table1(nom) VALUES('blabla1'); -- erreur, clé dupliqué car last_value de la séquence n'a pas été mis à jour

J'ai donc décider de creer une procedure qui met à jour cette valeur lors d'un update :

CREATE OR REPLACE FUNCTION updateNextvalTable1()
RETURNS TRIGGER
AS $$
DECLARE
	val bigint;
BEGIN
	SELECT max(id) INTO val FROM table1;
	val = val + 1;
	ALTER SEQUENCE table1_id_seq RESTART WITH val; -- erreur
	RETURN NEW;
END; $$ language 'plpgsql';

CREATE TRIGGER TriggerUpdateNextvalTable1
AFTER UPDATE
ON table1
FOR EACH ROW EXECUTE PROCEDURE updateNextvalTable1();

Probleme : il ne veut pas que je mette val mais un nombre (et non une variable)




Voici le code complet pour tester :

DROP TRIGGER IF EXISTS TriggerUpdateNextvalTable1 on table1;
DROP TABLE IF EXISTS table1 CASCADE;

CREATE TABLE table1
(
    id serial primary key,
    nom varchar(255) NOT NULL
);


CREATE OR REPLACE FUNCTION updateNextvalTable1()
RETURNS TRIGGER
AS $$
DECLARE
	val bigint;
BEGIN
	SELECT max(id) INTO val FROM table1;
	val = val + 1;
	ALTER SEQUENCE table1_id_seq RESTART WITH val;
	RETURN NEW;
END; $$ language 'plpgsql';

CREATE TRIGGER TriggerUpdateNextvalTable1
AFTER UPDATE
ON table1
FOR EACH ROW EXECUTE PROCEDURE updateNextvalTable1();



INSERT INTO table1(nom) VALUES('blabla1');
INSERT INTO table1(nom) VALUES('blabla1');
UPDATE table1 SET id = 3 where id = 2;
INSERT INTO table1(nom) VALUES('blabla1');
SELECT * from table1;

#9 Re : Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 30/09/2011 18:00:31

flo a écrit :

Je vais aller encore plus loin dans ce sens : pourquoi vouloir une série sans trous?

En fait j'ai une table qui pourrai potentiellement être très grande et du coup je ne pourrai plus rien entré au bout d'un moment à cause d'un id trop grand pour être stocké sur 32 bits ou autre (je dis ça mais je suis conscient que il y a peu de chance que ça arrive, c'est juste histoire de faire quelque chose de propre).


flo a écrit :

NB : attention la solution de votre programme en php ne fonctionne pas à cause de la concurrence. 2 éléments de la table peuvent se retrouver avec le même id (enfin je suppose que vous aurez défini l'id comme clé primaire, donc vous aurez sans doute plutôt une erreur de violation de l'unicité)

Je n'ai pas très bien compris se que tu a essayé de me dire, mais en gros je trouve le plus grand id avec des requêtes php, j'ajoute 1, et j'envoie mon insert avec ce nouvel id. Donc ça marche !



Merci pour vos réponse, alors je résume, en gros il est préférable d'utiliser un bigserial plutôt qu'un integer,
et comme il ne va pas toujours à l’élément tout à fait en dernier, je suis obligé de faire mon script php si vraiment je veux bien placé mon enregistrement comme ça ?

autre question : c'est mieux de mettre "id bigserial NOT NULL primary key" ?

#10 Général » Optimisation d'un id de table et l'insertion d'une nouvelle ligne » 30/09/2011 14:13:26

K-LiBR3
Réponses : 22

Bonjour,

J'aimerai poser une question qui vous paraitra peut être un peu simple mais qui a beaucoup d'importance pour moi.
J'ai toujours créer mes id de table différemment pendant mon apprentissage de postgresql, mais maintenant, je voudrai savoir :

Quel est la meilleur manière de créer un id de table ?

avant que vous ne répondiez, je vais expliquer ma façon de voir les choses :
je créer mon id de cette manière :

CREATE TABLE firstLevel
(
    id bigserial primary key, -- ou serial peu importe
    nom varchar(255) NOT NULL
);


Ensuite, pour insérer un enregistrement, 2 solutions :

- soit je fait :
INSERT INTO firstLevel(nom) VALUES('blabla');
Problème : il prend pas toujours le dernier id, en fait si par exemple j'ai 3 enregistrements, et que je supprime le 3eme, que ensuite j'en rajoute un de cette manière, il va automatiquement prendre l'id 4 --> il y aura donc un trou à l'id 3. Pire : j'en suis pas sur mais je crois qu'un fois il m'a ajouté mon enregistrement en milieu de table, dans un trou (je ne sait plus dans quel contexte j'étais) alors que justement je veux respecté un certain ordre !

- donc je créer un algo en php qui me donne le dernier id et j’insère de cette manière :
INSERT INTO firstLevel(id, nom) VALUES(monIdPHP, 'blabla'); -- Mauvais niveau optimisation !

Pourrait on créer un id d'une meilleur manière ? peut être un "integer NOT NULL" ou je ne sais pas ? Cela reviendra au même par rapport au dernier id ?


J’espère vous avoir bien exposé ma problématique, merci d'avance pour vos réponses !

#11 Re : Général » Echapement en postgresql pour l'apostrophe » 22/08/2011 21:40:18

ça fonctionne ^^^^ en plus j'ai résolu un deuxième problème grâce à ta solution !

#13 Général » Echapement en postgresql pour l'apostrophe » 22/08/2011 20:45:34

K-LiBR3
Réponses : 4

Bonjour,

Apres de nombreuse recherches, je n'arrive pas à comprendre comment faire un échapement.

C'est à dire faire tout simplement :

INSERT INTO truc VALUES('blabla \' blabla');

merci d'avance !

#14 Re : Général » Domaine de definition pour données de type text » 19/06/2011 21:32:55

merci pour la solution et ton conseil, j'ai changé le nom 'type' en 'contentType'  !

#15 Général » Domaine de definition pour données de type text » 19/06/2011 20:27:33

K-LiBR3
Réponses : 3

Bonjour,


J'aimerai savoir comment donnée un domaine de définition à une de mes données de type text, de ce genre :

CREATE TABLE thirdLevel
(
    id bigserial primary key,
    name varchar(255) NOT NULL,
    type varchar(255) NOT NULL DEFAULT 'info' CHECK type = 'info' OR type = 'exemple' OR type = 'lien'
);

merci d'avance.

#16 Re : Général » Clef qui se regenere automatiquement » 07/06/2011 16:52:32

effectivement sa sert a rien de faire ceci. C'est juste que je voulais avoir quelque chose d'ordonné. Mon site en php gère mieux quand c'est ordonné je crois (sa fait longtemps que je n'y ai pas touché)

#17 Général » Clef qui se regenere automatiquement » 07/06/2011 16:37:07

K-LiBR3
Réponses : 3

Bonjour,

Je voudrais savoir comment faire pour que les clef se remette automatiquement dans l'ordre.

Par exemple, je creer cette table :

DROP TABLE IF EXISTS firstLevel CASCADE;
CREATE TABLE firstLevel
(
    id serial NOT NULL,
    PRIMARY KEY (id),
    name varchar(255) NOT NULL
);

J’insère ceci :
INSERT INTO firstLevel VALUES(0, 'blabla');
INSERT INTO firstLevel VALUES(1, 'blabla');
INSERT INTO firstLevel VALUES(2, 'blabla');
INSERT INTO firstLevel VALUES(3, 'blabla');
INSERT INTO firstLevel VALUES(4, 'blabla');

Ensuite, je supprime l'id 2 :
DELETE FROM firstLevel WHERE id = 2;

et que en conséquence, l'id 3 se mette en id 2 et que l'id 4 se mette en id 3 !


Peut on faire ceci sans fonctions php ou plgpsql ? Soit par une chose existante du genre "auto_increment"...  soit par une règle ?


Merci d'avance.

#18 Re : PHP » Probleme au niveau logiciels... postgres et php » 28/03/2011 20:10:59

Je vais refaire tout dans les règles de l'art et en essayant de comprendre
Je vous dirai si ça ne marche pas ^^ merci pour votre aide en tout cas !!!

#19 Re : PHP » Probleme au niveau logiciels... postgres et php » 27/03/2011 17:18:24

Rebonjour,

En fin de compte sa ne marche pas :S j'ai tout essayé mais rien à faire, il ne connait pas pg_connect !

#20 Re : PHP » Probleme au niveau logiciels... postgres et php » 25/03/2011 16:04:54

Ok merci je vais essayé.

Une dernière question ^^ : est ce que tu sais si on peut utilisé le language plpgsql chez free parce que apparemment tout le monde dit, sur les forum, qu'on ne peut pas.. bien dommage, il faut donc ce payer un vrai nom de domaine etc pour pouvoir utiliser les fonctions :S

#21 Re : PHP » Probleme au niveau logiciels... postgres et php » 25/03/2011 15:43:36

Connais tu un package ou un tutoriel clair qui me permettrai de résoudre mon probleme ?

#22 PHP » Probleme au niveau logiciels... postgres et php » 25/03/2011 14:47:14

K-LiBR3
Réponses : 11

Bonjour,

Lorsque je lance ce script php :

<?php
    $connect = pg_connect("host=localhost port=5432 dbname=hayj user=root password=postgres");
    if(!$connect) { echo "<p>La connection à la base a échoué - Fin du programme.</p>\n"; exit; }

    $query = pg_query($connect, "SELECT * FROM maTable");
    if(!$result) { echo "<p>La requête a échoué - Fin du programme.</p>\n"; exit; }

    while($row = pg_fetch_array($query, NULL, PGSQL_BOTH))
    {
        echo "Voici une ligne de maTable : $row[0]";
        echo "<br />\n";
    }
?>

Il me dit qu'il ne connait pas la fonction pg_connect alors que j'ai suivit ce tutoriel http://www.siteduzero.com/tutoriel-3-11 … erver.html (que j'ai réessayé 7 fois)
A côté de ça, je suis connecté sur la base avec pgadmin, donc le serveur est bien lancé et sa devrai fonctionner théoriquement non ?

merci d'avance pour vos réponses ^^

Pied de page des forums

Propulsé par FluxBB