web-dev-qa-db-fra.com

avec insert on duplicate key update - mise à jour de plusieurs lignes à la fois

Avec la dernière version de joomla, j'essaie de réaliser une requête dans la base de données et de mettre à jour plusieurs lignes à la fois.

Je veux faire une requête comme ceci:

INSERT INTO `tablename`
(`id`,`date`) VALUES 
('79','2018-12-01'),('78','2018-10-01'),('76','2018-06-01'),('80','2019-01-01')
ON DUPLICATE KEY UPDATE
(`date` = '2018-12-01'),(`date` = '2018-10-01'),(`date` = '2018-06-01'),(`date` = '2019-01-01')

Si j'installe ceci et débogue:

$query
        ->insert($db->quoteName('#__tablename'))
        ->columns($db->quoteName($columns))
        ->values($values);

cela ne produit que les 3 premières lignes de ma requête souhaitée. Comment puis-je prolonger pour ajouter le texte "ON DUPLICATE KEY UPDATE" et une autre valeur de tableau à la fin? Ou il y a une autre façon de faire ça? Il est possible d’ajouter plusieurs requêtes à setQuery ou de concaténer des requêtes?

3
almost okey

Construire une requête REPLACE INTO Est aussi simple que de construire un INSERT ... ON DUPLICATE KEY UPDATE. Notez que il y a une différence entre REPLACE INTO ET ON DUPLICATE KEY UPDATE .

Code:

$columns = ['id', 'date'];
$data = [
    [79, '2018-12-01'],
    [78, '2018-10-01'],
    [76, '2018-06-01'],
    [80, '2019-01-01']
];

$db = JFactory::getDbo();
try {
    foreach ($data as &$row) {
        $row = (int)$row[0] . ", " . $db->q($row[1]); // flatten 2-dim array and apply security techniques
    }
    $query = $db->getQuery(true)
                ->insert($db->qn('#__tablename'))
                ->columns($db->qn($columns))
                ->values($data);
    $db->setQuery(substr_replace($query, 'REPLACE', 0, 8));    // swap INSERT for REPLACE
    // in other words: $db->setQuery(str_replace("\r\nINSERT", "REPLACE", $query));
    // or:             $db->setQuery(preg_replace("~^\s+INSERT~", "REPLACE", $query));
    // Joomla puts \r\n at the start of the query; see via var_dump($db) after setQuery()
    /*
    echo "<pre>";
        print_r($db);   // see the updated sql object
    echo "</pre>";
    */
    $db->execute();
} catch (Exception $e) {
    echo  "Syntax Error: " , $e->getMessage();  // never show php's error message to the public
}
echo "<div>" , $db->getAffectedRows() , " row(s) inserted</div>";

C'est la requête construite:

REPLACE INTO `#__tablename`
(`id`,`date`) VALUES 
(79, '2018-12-01'),(78, '2018-10-01'),(76, '2018-06-01'),(80, '2019-01-01')

Cela [~ # ~] toujours [~ # ~] affichera le même nombre de lignes concernées pour votre lot de quatre entrées:

4 rangée (s) insérée (s)



Pour ce qui est de ON DUPLICATE KEY UPDATE..., Il suffit d'ajouter la clause à la fin de la requête générée par Joomla et d'inclure la syntaxe VALUES() . (seulement remplace la ligne $db->setQuery() de l'extrait de code ci-dessus)

$db->setQuery($query . " ON DUPLICATE KEY UPDATE `date` = VALUES(`date`)");

pour créer cette requête:

INSERT INTO `#__tablename`
(`id`,`date`) VALUES 
(79, '2018-12-01'),(78, '2018-10-01'),(76, '2018-06-01'),(80, '2019-01-01')
ON DUPLICATE KEY UPDATE `date` = VALUES(`date`)

Ce type de requête se comporte différemment et donne un retour différent en termes de lignes affectées.

Lorsque des lignes identiques existent dans la table de base de données pour toutes les lignes que vous souhaitez ajouter, vous verrez les lignes 0 Affectées. Si l'ID PRIMARY existe déjà - disons qu'une ligne a une valeur date différente de celle de la requête - vous verrez les lignes 2 Affectées (je l'ai exécuté sur mon propre localhost et malgré les autres choses que j'ai lues, cela doit être enlevé, puis ajouté). Ce type d’information peut donc être très utile ou très confus, selon ce que vous essayez de déterminer. Imaginez si les quatre ids sont déjà représentés dans votre table et que deux des quatre lignes nécessitent la mise à jour de la valeur date. Une fois la requête exécutée, vous serez averti que les lignes 4 Ont été affectées.

Voici ne réponse pertinente que j'ai postée il y a quelques années sur StackOverflow .

2
mickmackusa