8797 sujets

Développement web côté serveur, CMS

Bonjour,

Je suis nouvellement inscrit au forum de Alsa Créations.

J'arrive avec un problème qui me casse la tête depuis quelques jours.

J'utilise une base de données MySQL pilotée sous PhpMyAdmin dont voici la structure :

id_hotel (int 3, index),
date(var char 10, index),
lit (int3, primary key)

Ma page HTML contient divers champs "text" de formulaire dont le "name" est égal à une date...

Ex : <input type="text" name="10/05/2012" />

J'ai 30 champs de ce type sur la page.

J'ai eu vent de "On Duplicate Key Update" que je souhaiterais adapter à mon projet de sorte que je n'ai plus à gérer Insert ou Update.

Ma Requête qui ne fonctionne pas :
insert into matable (id_hotel, date, lit) VALUES ('1','10/05/2012','2'), ('1','11/05/2012','4'), ('1','12/05/2012','6') ON DUPLICATE KEY UPDATE lit=VALUES(lit)

J'ai beaucoup cherché sur la toile avant de poster ce message mais mes recherches restent infructueuses.

J'espère recevoir un peu d'aide ici.

Merci à toutes et à tous.
Déjà, fait attention, ta primary key, sur laquelle va se faire le "on duplicate key", c'est le champ "lit".

Sinon pour ta requête, le problème est dans le "UPDATE lit=VALUES(lit)"

Derrière le lit= il te faut une valeur directement. (comme dans un "update `ma_table` set `mon_champ`="valeur")
Merci pour ta réponse Lothindil.

La clé primaire doit se trouver sur quel champ ?

As-tu un exemple concret à me fournir pour ma requête car c'est un sac de noeuds pour moi...

Merci.
Yop,

Généralement, la clé primaire est le champ ID. Ce qui permet de distinguer chaque élément.
Le principe c'est d'une clé primaire (et par la suite du "on duplicate key"), c'est d'être un champ unique, propre à chaque enregistrement. Typiquement, c'est le cas des champs ID. Cependant, il peut être multiple (2 ou 3 champs ensemble qui forment une clé primaire.)

Quelques exemples tirés de mon propre code (code d'un jeu) :
- table des personnages. Chaque personnage possède son propre identifiant qui est unique et qui me permet de le relier à ses différentes données sur d'autres tables. La structure, ressemble à ça :
id(int,primary key)
nom (varchar)
classe (enum)
race (enum)
skin (var char)

- table de l'historique des quêtes. Chaque personnage peut avoir plusieurs quêtes finies et chaque quête peut être finie par plusieurs personnes. La structure devient :
idPj (int, primary key) : c'est l'id du personnage
idQuete (int, primary key) : c'est l'id de la quête
nombre (tinyint) : le nombre de fois que la quête a été validé par ce personnage.

J'utilise souvent le insert ... on duplicate key... pour l'historique des quêtes. Cela permet d'augmenter le nombre de fois que le personnage a fini la quête sans devoir vérifier s'il l'a déjà fini une fois. La requête ressemble à ça :

a écrit :
insert into histo_quetes (idPj,idQuete,nombre) values (3,410,1) on duplicate key update `nombre`=`nombre`+1


Ce qui se traduit en Français par : Tu tentes d'insérer les valeurs (3,410,1) dans les champs (idPj,idQuete,nombre) de la table histo_quetes et si tu arrives à une erreur de clé unique dupliquée (en gros si tu as déjà un enregistrement de type : (3,410,...)), tu ajoutes 1 au champ "nombre" de cet enregistrement. Smiley ravi

Dans le code php, ça donne ça (en véritable spaghetti):
a écrit :
$sql=mysql_query("insert into histo_quetes (idPj,idQuete,nombre) values (".$idPj.",".$idQuete.",1) on duplicate key `nombre`=`nombre`+1




Dans ton cas, il faut d'abord réfléchir au sens réel de tes données :

- id_hotel : il représente quoi ?
- Date : ça représente quoi ?
- lit : ça représente quoi ?

Quelle(s) donnée(s) ne doit jamais se retrouver en double dans tes tables ?

Si tu as déjà un enregistrement qui ressemble à ça : (1;01/01/2013;1)

est-ce que tu peux avoir un enregistrement qui ressemble à :
A) (1;02/01/2013;2) >> si non, ta clé primaire doit être id_hotel
B) (2;01/01/2013;2) >> si non, ta clé primaire doit être date
C) (2;02/01/2013;1) >> si non, ta clé primaire doit être lit
D) (1;01/01/2013;2) >> si non et si A et B est possible, ta clé primaire est le couple id_hotel;date
E) (1;02/01/2013;1) >> si non et si A et C est possible, ta clé primaire est le couple id_hotel;lit
F) (2;01/01/2013;1) >> si non et si B et C sont possibles, ta clé primaire est le couple date;lit
Modifié par Lothindil (10 May 2012 - 14:16)
Merci Lothindil pour ton message.

Je vais tenter d'exposer plus en détail mon projet afin que tu cernes au mieux ma demande.

J'ai créé une page permettant de définir pour une date donnée un nombre de lits dans
un hôtel.

Sur cette même page, je peux définir un nombre de lits pour 30 jours et sur 3 hôtels différents.

id_hostel => correspond à l'identifiant de l'hôtel (1,2 ou 3)
date => date à laquelle je définis un nombre de lits pour l'hôtel donné
lit => nombre de lits affectés à l'hôtel à la date prédéfinie

Ma page HTML ressemble donc à ceci :

<form>

<div style="float:left">
<p>10/05/2012</p>
<p><input type="text" name="10/05/2012" maxlength="3" /></p>
</div>

<div style="float:left">
<p>11/05/2012</p>
<p><input type="text" name="11/05/2012" maxlength="3" /></p>
</div>

<div style="float:left">
<p>12/05/2012</p>
<p><input type="text" name="12/05/2012" maxlength="3" /></p>
</div>

... etc

</form>

La page affiche ou non la value des différents champs si elle existe.
Ex. pour la date du 10/05/2012, si j'ai une valeur de lit, elle s'affiche dans le champ prévu à cet effet.

Je réponds à tes questions (points A à F) :

est-ce que tu peux avoir un enregistrement qui ressemble à :
A) (1;02/01/2013;2) >> si non, ta clé primaire doit être id_hotel (oui, je peux avoir cette configuration)
B) (2;01/01/2013;2) >> si non, ta clé primaire doit être date (oui, je peux avoir cette configuration)
C) (2;02/01/2013;1) >> si non, ta clé primaire doit être lit (oui, je peux avoir cette configuration)
D) (1;01/01/2013;2) >> si non et si A et B est possible, ta clé primaire est le couple id_hotel;date (oui, je peux avoir cette configuration)
E) (1;02/01/2013;1) >> si non et si A et C est possible, ta clé primaire est le couple id_hotel;lit (NON, je dois dans ce cas mettre à jour mon champ point A, la nouvelle valeur de lit vient écraser l'ancienne en fait)
F) (2;01/01/2013;1) >> si non et si B et C sont possibles, ta clé primaire est le couple date;lit (NON, je dois dans ce cas mettre à jour mon champ point A, la nouvelle valeur de lit vient écraser l'ancienne en fait)

Il est peut être possible que mes besoins ne puissent être assouvis par l'utilisation de "On Duplicate Key Update" mais par "Replace Into" mais dans les deux cas, dès que je valide ma page à l'aide du bouton SUBMIT, j'ai un enregistrement créé quelque soit le cas de figure.

Suis-je dans l'impasse ? Smiley cligne

Un grand Merci !!!
En gros, tu dois pouvoir arriver à ceci comme affichage (en plus joli certes)

http://www.yuimen.com/img/table.png


Si c'est bien le cas, ta clé primaire est simple à trouver, car il n'y a qu'une seule case pour chaque croisement. Pour chaque couple (date/id_hotel), il n'y a qu'un seul nombre de lit.

Dans ce cas-là, faudrait changer ta table pour faire que id_hotel et date soit tous deux des "primary key".
Modifié par Lothindil (10 May 2012 - 19:53)
Ton tableau est représentatif de ce que je souhaite en effet.

Dans PhpMyAdmin, je n'arrive pas à mettre une clé primaire sur deux champs différents :s
PhpMyAdmin m'en empêche en m'indiquant une erreur "Undefined"

Je vais regarder à nouveau dans PhpMyAdmin et reviens vers toi.

Merci.