2017-07-16 2 views
2

Je dois faire une requête, qui insère-ou-met à jour en 1 ligne.Insertion SQL compliquée-mise à jour avec sélection interne

EDIT: J'ajoute le WORKING requête SQL ici.

$this->sqlSavePlot = $this->db->prepare(
     "INSERT OR REPLACE INTO plots (id, level, X, Z, name, owner, helpers, denied, biome) VALUES 
     ((select id from plots where level = :level AND X = :X AND Z = :Z), 
     :level, :X, :Z, :name, :owner, :helpers, :denied, :biome);" 
    ); 

Théoriquement je veux la même chose dans les états MySQL préparés

Actuellement le désordre ressemble à ceci:

$this->sqlSavePlot = $this->db->prepare(
     "INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`) 
     VALUES(id = (SELECT id FROM plots WHERE level = level AND X = VALUES(X) AND Z = VALUES(Z)), level = ?, X = ?, Z = ?, name = ?, owner = ?, helpers = ?, denied = ?, biome = ?) 
     ON DUPLICATE KEY UPDATE 
      id = VALUES(id), 
      level = VALUES(level), 
      X = VALUES(X), 
      Z = VALUES(Z), 
      name = VALUES(name), 
      owner = VALUES(owner), 
      helpers = VALUES(helpers), 
      denied = VALUES(denied), 
      biome = VALUES(biome);" 
    ); 

Comme vous le voyez, assez chaotique.

Voici comment la base de données ressemble à:

The database

Donc, en théorie, si l'utilisateur exécute la fonction savePlot, plusieurs champs sont remplacés, comme vous pouvez le voir dans le code PHP . « sqlSavePlot » est la requête que j'ai montré

Pour une explication plus profonde du code PHP:

public function savePlot(Plot $plot): bool{ 
    print "------------------------------------------------------".PHP_EOL; 
    $this->db->ping(); 

    $helpers = implode(',', $plot->helpers); 
    $denied = implode(',', $plot->denied); 
    if ($plot->id <= 0){ 
     $stmt = $this->sqlSavePlot; 
     $stmt->bind_param('siisssss', $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome); 
    } else{ 
     $stmt = $this->sqlSavePlotById; 
     $stmt->bind_param('isiisssss', $plot->id, $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome); 
    } 
    $result = $stmt->execute(); 
    var_dump($stmt); 
    var_dump($result); 
    var_dump($plot); 
    $this->lastSave = time(); 

    if ($result === false){ 
     $this->plugin->getLogger()->error($stmt->error); 
     return false; 
    } 
    $this->cachePlot($plot); 
    return true; 
} 

si « vide » id d'un terrain peut être soit -1, ou avoir une carte d'identité qui est tiré par les cheveux de la fonction savePlot

Je sais que la partie foiré est autour des premiers « valeurs »:

Vous avez une erreur dans votre syntaxe SQL; vérifier le manuel que correspond à votre version du serveur MySQL pour la bonne syntaxe à utiliser près de??, X =?, Z =?, nom =?, propriétaire =?, helpers =?, refusé =?, biome =?) 'à la ligne 2

Quelqu'un pourrait-il m'expliquer ce que je pourrais mettre à la place?

EDIT: comme l'a demandé, SHOW CREATE TABLE

CREATE TABLE `plots` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`level` text COLLATE utf8_unicode_ci, 
`X` int(11) DEFAULT NULL, 
`Z` int(11) DEFAULT NULL, 
`name` text COLLATE utf8_unicode_ci, 
`owner` text COLLATE utf8_unicode_ci, 
`helpers` text COLLATE utf8_unicode_ci, 
`denied` text COLLATE utf8_unicode_ci, 
`biome` text COLLATE utf8_unicode_ci, 
PRIMARY KEY (`id`), 
KEY `XZ` (`X`,`Z`) 
) ENGINE=InnoDB AUTO_INCREMENT=3609 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 
+1

S'il vous plaît ajouter des informations de 'SHOW CREATE TABLE parcelles». Expliquez aussi ce que vous essayez de faire. Une requête qui ne fonctionne pas ne peut pas le faire pour vous. –

+0

Ajouté comme demandé – thebigsmileXD

Répondre

0

Je pense que vous voulez faire quelque chose comme:

INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`) 
    SELECT id, p.level, p.X, p.Z, ?, ?, ?, ? 
    FROM plots p 
    WHERE p.level = ? AND X = ? AND Z = ? 
    ON DUPLICATE KEY 
     UPDATE name = VALUES(name), 
       owner = VALUES(owner), 
       helpers = VALUES(helpers), 
       denied = VALUES(denied), 
       biome = VALUES(biome); 

Vous devez faire attention à l'ordre des arguments. Je devine que id est la clé primaire et (X, Z, level) est déclaré comme unique (comment vous identifiez les doublons). Vous spécifiez seulement que vous voulez changer de nom en cas de collision, mais cela définit toutes les valeurs (comme dans votre version).

+0

J'ai ajouté plus d'informations à ma question, par exemple la requête SQL que je veux traduire en mysql et l'apparence de la base de données. – thebigsmileXD

0

fixe ma requête avec la réponse fournie par @Gordon Linoff

s'avère i même eu un problème logique .. i mélangé le « saveByID » et « saveByXZ » ..

public function savePlot(Plot $plot): bool{ 
    $this->db->ping(); 
    $helpers = implode(',', $plot->helpers); 
    $denied = implode(',', $plot->denied); 

    if ($plot->id >= 0){ 
     $stmt = $this->sqlSavePlotById; 
     $stmt->bind_param('isiisssss', $plot->id, $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome); 
    } else{ 
     $stmt = $this->sqlSavePlot; 
     $stmt->bind_param('siisiisssss', $plot->levelName, $plot->X, $plot->Z, $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome); 
    } 
    $result = $stmt->execute(); 
    $this->lastSave = time(); 

    if ($result === false){ 
     $this->plugin->getLogger()->error($stmt->error); 
     return false; 
    } 
    $this->cachePlot($plot); 
    return true; 
} 

fixe en requête:

$this->sqlSavePlot = $this->db->prepare(
     "INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`) 
VALUES((SELECT id 
FROM plots p 
WHERE p.level = ? AND X = ? AND Z = ?),?,?,?,?,?,?,?,?) 
ON DUPLICATE KEY 
    UPDATE name = VALUES(name), 
      owner = VALUES(owner), 
      helpers = VALUES(helpers), 
      denied = VALUES(denied), 
      biome = VALUES(biome);" 
    ); 
    $this->sqlSavePlotById = $this->db->prepare(
     "UPDATE plots SET id = ?, level = ?, X = ?, Z = ?, name = ?, owner = ?, helpers = ?, denied = ?, biome = ? WHERE id = VALUES(id);" 
    ); 

Merci beaucoup à tout le monde! J'espère que cela aidera les autres à l'avenir!