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 09/07/2012 18:14:59

Marco
Membre

Contraintes SQL sur attribut et traitement des erreurs en PHP

salut a tous,
Sur une table, je définis en SQL une contrainte genre : CONSTRAINT c1 CHECK(pd_prix >3)

Dans mon application PHP, si je saisis un prix de 1, lors de l'exécution du code php :
   $query= "INSERT INTO produit( pdt_designation, pdt_prix, pdt_categorie,pdt_datecrea)
  VALUES ( '$_POST[fdesignation]',$_POST[fprix],'$_POST[fcategorie]','$datecre')";   
  pg_query($query)or die( "erreur requete" );

l'erreur est détectée (très bien) :
Warning: pg_query() [function.pg-query]: Query failed: ERREUR: la nouvelle ligne viole la contrainte de vérification «c1» de la relation «produit2» in C:\Docum....   ajoutersql2.php on line 16  : pg_query($query)or die( "erreur requete" );
erreur requete

L'erreur est détectée mais PLANTE le programme. Il faut donc détecter l'erreur avant l'exécution de la rqt par pg_query($query), est ce possible ? Et comment l'indiquer proprement à l'utilisateur, reprendre la main et revenir à la saisie ?
Je ne vois pas de meilleure solution (et c'est là que je fais appel à vous) que de faire la verif en JavaScript dans le formulaire HTML de saisie.

Si la meilleure solution est Javascript alors quand est il utile de gérer les contraintes en SQL !

Merci pour vos commentaires.

Hors ligne

#2 09/07/2012 21:06:23

rjuju
Administrateur

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Bonjour, l'instruction die() est justement là pour quitter le script en affichant un message. Vous devriez plutôt faire une transaction si besoin, tester le retour de pg_query et rendre la main en gérant les erreurs possibles.


Vous pouvez le faire en javascript, mais cela exigera de gérer vos définitions de contraintes à la fois dans postgres et dans javascript, ou de faire des requêtes pour interroger le catalogue pour essayer de retrouver dynamiquement les contraintes associées aux champs.

Hors ligne

#3 09/07/2012 23:55:28

gleu
Administrateur

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Pour répondre à l'intérêt d'ajouter les contraintes en base, il est double :

1. pour éviter que n'importe qui connecté à la base ne puisse pas y placer des données qui n'ont aucun sens (dans votre cas, un pd_prix<=3)
2. pour donner des informations au planificateur qui lui permet de mieux optimiser les requêtes.


Guillaume.

Hors ligne

#4 10/07/2012 08:43:02

Marco
Membre

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Merci de vos réponses mais je cherche toujours la solution.

Réponse à rjuju :
->  "die() est justement là pour quitter le script en affichant un message"
oui mais mon programme est planté avec le message :
  'Warning: pg_query() [function.pg-query]: Query failed: ERREUR: la nouvelle ligne viole la contrainte de   vérification «c1» de la relation «produit2» in C:\Docum....   ajoutersql2.php on line 16  : pg_query($query)or die( "erreur requete" );
erreur requete'
Cela ne me convient pas.

  ->  "Vous devriez plutôt faire une transaction si besoin, tester le retour de pg_query et rendre la main en gérant les erreurs possibles"
J'avais pensé plutôt à un Trigger sur Ajout et sur Modification mais comment récupérer le code de l'erreur (j'ai trouvé) mais le lieu de l'erreur car j'ai bien sur plusieurs contraintes sur la table, elles sont nommées (ici 'c1' dans l'exemple donné).
Comment récupérer le nom (ou les noms) de la contrainte qui plante . Est ce que seulement la première contrainte qui est en erreur est détectée ou toutes ?
Comment depuis Postgres afficher un message sur mon écran, j'ai bien trouvé dans des CREATE FUNCTION la commande : RAISE EXCEPTION $$ texte  % texte $$OLD.champ ;
Comment depuis mon fichier ajoutersql2.ph dans lequel je fais mon INSERT qui plante (ou pose problème si je capte le problème avant le plantage) revenir à mon fichier ajouterform.ph pour reproposer le formumaire.

Faire la vérification en PHP/Javascript AVANT l'INSERT, je sais faire mais je perds totalement l’intérêt du CONSTRAINT SQL du CREATE centralisé dans la BD.


Réponse à gleu :
  -> "pour éviter que n'importe qui connecté à la base ne puisse pas y placer des données qui n'ont aucun sens"
D'accord mais ma table Produit n'est accessible que par mon application PHP et c'est donc là (et uniquement là) que je veux éviter d'y placer des données qui n'ont aucun sens.

Hors ligne

#5 10/07/2012 09:24:12

rjuju
Administrateur

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Le message est un warning pour vous informer de l'erreur, il n'arrête pas le traitement. Le script est arrêté par le die().
Si vous ne voulez pas afficher le warning, vous pouvez mettre un @ devant votre pg_query(), ou configurer votre php pour qu'il n'affiche pas la sortie des warnings.

Vous devez par contre faire un traitement du genre :

$res = pg_query($query);
if ($res) {
//le traitement est ok on continue
}
else{
// gestion de l'erreur
}

Hors ligne

#6 10/07/2012 09:33:17

gleu
Administrateur

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Rien n'empêche qu'une partie de votre application soit mal codé (un bug tout bêtement), et qui ajoute des données qui n'ont pas de sens.

En ce qui concerne l'ajout d'un trigger, c'est certainement le meilleur moyen de perdre en performance.

Et pour répondre aux questions :

Comment récupérer le nom (ou les noms) de la contrainte qui plante.

Pas sûr que vous puissiez, pas sûr que ça a un intérêt non plus. L'important est de connaître le type de l'erreur et d'y répondre. Comment se fait-il d'ailleurs que l'application permette la saisie d'une information qui n'a pas de sens ?

Est ce que seulement la première contrainte qui est en erreur est détectée ou toutes ?

La première. Chercher toutes les erreurs serait une perte en performance.

Comment depuis Postgres afficher un message sur mon écran

PostgreSQL n'a pas à afficher quoi que ce soit. C'est un moteur de bases de données. C'est à votre application de gérer l'affichage suivant la réussite ou l'échec des opérations.

j'ai bien trouvé dans des CREATE FUNCTION la commande : RAISE EXCEPTION $$ texte  % texte $$OLD.champ ;

RAISE n'a pas pour but d'afficher une erreur sur l'application mais d'enregistrer un message dans les traces de PostgreSQL. RAISE EXCEPTION va en plus annuler la procédure en erreur.

Comment depuis mon fichier ajoutersql2.ph dans lequel je fais mon INSERT qui plante (ou pose problème si je capte le problème avant le plantage) revenir à mon fichier ajouterform.ph pour reproposer le formumaire.

Aucune idée, c'est plutôt pour un forum PHP, cette question smile

Faire la vérification en PHP/Javascript AVANT l'INSERT, je sais faire mais je perds totalement l’intérêt du CONSTRAINT SQL du CREATE centralisé dans la BD.

Comme expliqué dans ma précédente réponse, non, vous ne le perdez pas. Elle empêche toute saisie de mauvaise information dans la base, quelque soit le moyen employé. À votre application de réagir convenablement aux erreurs. À votre application aussi d'éviter la saisie de données qui n'ont aucun sens. Par exemple, dans le cas proposé, si l'utilisateur saisit 3, la fonction d'enregistrement peut empêcher l'INSERT s'il sait que 3 est une valeur qui n'a pas de sens. L'intelligence ne doit pas être que dans la base de données, mais aussi dans l'application.


Guillaume.

Hors ligne

#7 11/07/2012 11:32:44

Marco
Membre

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Merci à gleu et rjuju pour vos  réponses .

J'y vois plus clair.
Postgres me dit simplement que je suis en erreur, via le code d'erreur je trouve le type d'erreur derrière lequel j'ai plusieurs erreurs possibles du même type. A moi de les tester.

Cependant :
Il me semble que si j'ai 2 erreurs  de 2 types, le sgbd m'informe seulement de la première erreur (gleu:"La première. Chercher toutes les erreurs serait une perte en performance." ). Donc, je cherche uniquement l'erreur ou les erreurs de type1, j'affiche en (php/javascript) un message à l'utilisateur, je ré-affiche le formulaire de saisie, l'utilisateur corrige l'erreur ou les erreurs de type1, poste le formulaire, le sgbd détecte l'erreur de type2 et je recommence comme ci-dessus. Si j'ai des erreurs sur un gros formulaire de 6 types et que l'utilisateur itéré 6 fois sur la correction du formulaire, il va pas être content !

Il me semble donc préférable de tester systématiquement TOUTES les erreurs avant le "pg_query($query)" et même avant le postage du formulaire et donc  sans alerte du sgbd via les contraintes et proposer à l'itilisateur la correction en 1 seule passe de  toutes les erreurs.
Si j'ai bien compris  l'alerte du sgbd m'est que moyennement utile (à moins qu'il y ai mieux à faire)...

Peut on mieux faire ?

Hors ligne

#8 11/07/2012 13:09:52

gleu
Administrateur

Re : Contraintes SQL sur attribut et traitement des erreurs en PHP

Encore une fois, il faut bien faire la distinction entre l'application et la base de données. La base de données contient certaines contraintes qui empêchent n'importe quelle application de mettre n'importe quoi dans la base. L'application doit faire de même si elle souhaite contenter son utilisateur au niveau de son interaction. Donc, oui, vous devez aussi mettre des gardes-fous sur l'application, mais non, ce n'est pas inutile de les mettre aussi dans la base.


Guillaume.

Hors ligne

Pied de page des forums