[RESOLU] INSERT avec jointure

Eléphant du PHP | 345 Messages

21 juin 2021, 09:07

Bonjour,
J'ai un soucis avec la fin de cette requête (la phase INSERT).
$sql = "UPDATE membres SET pos_x = pos_x, pos_y= pos_y+1 WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();

$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat )) { 
$pos_x = $resultat['pos_x'];
$pos_y = $resultat['pos_y'];
}
$sql =  "INSERT INTO map (pos_x, pos_y)  SELECT ('$pos_x','$pos_y')  FROM membres WHERE id= $id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
Cardinality violation: 1241 Operand should contain 1 column(s) in C:\wamp64

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

21 juin 2021, 10:03

Vérifie la syntaxe de INSERT INTO ... SELECT car pour moi ça doit être des noms de colonnes dans le SELECT et non pas des valeurs.

Par ailleurs, si tu utilises une requête préparée alors tu ne devrais pas avoir de variables PHP dans ta requête : ($id, $pos_x, $pos_y) : revérifie la syntaxe pour insérer des variables avec bindvalue(), et profites en pour y passer aussi $pos_x, $pos_y
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Eléphant du PHP | 70 Messages

22 juin 2021, 10:07

Je confirme il s'agit bien du nom des colonnes et non des variables : https://www.mysqltutorial.org/mysql-insert-into-select/

Le but du INSERT INTO SELECT est de ne pas avoir besoin d'aller chercher le contenu d'une autre table et de refaire une requête avec ces variables
" La révolution informatique fait gagner un temps fou aux Hommes, mais ils le passent avec leur ordinateur ! " by Khalil Assala

Eléphant du PHP | 345 Messages

22 juin 2021, 10:21


$sql =  "INSERT INTO map (pos_x, pos_y)  SELECT (pos_x,pos_y)  FROM membres WHERE id= :id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':pos_x',$pos_x ,PDO::PARAM_INT);
$pdostat->bindvalue(':pos_y',$pos_y ,PDO::PARAM_INT);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);

$pdostat->execute();
ne fonctionne pas encore et je ne comprends pas comment faire

Avatar du membre
Eléphant du PHP | 70 Messages

22 juin 2021, 10:38

ça ne fonctionne pas car tu essaye de faire un bindValue sur :pos_x alors que tu ne la pas mis dans ta requete, idem pour :pos_y

A tu regarder le lien que je tes envoyé ?

Dans ta table membres, tes colonnes s'appellent bien pos_x et pos_y ? idem pour ta table map ?
" La révolution informatique fait gagner un temps fou aux Hommes, mais ils le passent avec leur ordinateur ! " by Khalil Assala

Eléphant du PHP | 345 Messages

22 juin 2021, 10:43

Invalid parameter number: number of bound variables does not match number of tokens in C:
$sql =  "INSERT INTO map (pos_x, pos_y)  SELECT (pos_x,pos_y)  FROM membres WHERE id= :id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue('pos_x',$pos_x ,PDO::PARAM_INT);
$pdostat->bindvalue('pos_y',$pos_y ,PDO::PARAM_INT);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();

Eléphant du PHP | 345 Messages

22 juin 2021, 10:45

oui, les colonnes portent le meme nom dans les deux tables et oui j'ai regardé ton lien et c'est ce que je ne comprends pas.
si je mets les : avec pos_x et pos_y dans la requete ca ne marche pas non plus.

Avatar du membre
Eléphant du PHP | 70 Messages

22 juin 2021, 10:47

ça ne fonctionne pas car tu essaye de faire un bindValue sur :pos_x alors que tu ne la pas mis dans ta requete, idem pour :pos_y
Tu n'a pas fait les modifications. Tu as 2 bindValue en trop

Tu doit passer des nom de colonnes, pas des valeurs

INSERT INTO map(pos_x,pos_y) //Le nom de tes colonnes dans la tables map
SELECT
(pos_x,pos_y) //Le nom de tes colonnes dans la tables membres
FROM
membre
WHERE
id = :id;
" La révolution informatique fait gagner un temps fou aux Hommes, mais ils le passent avec leur ordinateur ! " by Khalil Assala

Eléphant du PHP | 345 Messages

22 juin 2021, 16:11

Fatal error: Uncaught PDOException: SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s) in C:\wamp64\www\map_maj.php on line 8
( ! ) PDOException: SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s) in C:\wamp64\www\map_maj.php on line 8
<?php
session_start();
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql =  "INSERT INTO map (pos_x, pos_y)  SELECT (pos_x,pos_y)  FROM membres WHERE id= :id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
?>

Eléphant du PHP | 345 Messages

22 juin 2021, 16:54

j'ai essayé avec:
$sql = "UPDATE map INNER JOIN  membres ON  membres.pos_x = map.pos_x AND membres.pos_y = map.pos_y
SET  map.pos_x = membres.pos_x, map.pos_y = membres.pos_y WHERE membres.id=$id";
$pdostat = $bdd->prepare($sql);
$pdostat->execute();
mais aucune modif dans la table map.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

22 juin 2021, 16:57

Salutations !

Il ne faut pas de parenthèses autour de la liste des colonnes retournées par le select. Il faut commencer par construire une requête de type select valide, que tu pourra ensuite facilement inclure dans ton insert : "SELECT pos_x, pos_y FROM membres WHERE id= :id" :)

Edit : euh... pourquoi ce update ? tes enregistrements existent déjà dans ta table map (auquel cas c'est effectivement un update qu'il faut pour les mettre à jour), ou au contraire tu veux les créer (et dans ce cas, c'est un insert dont tu as besoin)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 345 Messages

22 juin 2021, 23:51

Merci Ryle.
<?php
session_start();
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql =  "INSERT INTO map (pos_x, pos_y)  SELECT pos_x,pos_y  FROM membres WHERE id= :id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
?>