web-dev-qa-db-ja.com

重複キー更新の挿入あり-複数の行を一度に更新

最新のjoomlaバージョンでは、データベースに対して1つのクエリを実行し、一度に複数の行を更新しようとしています。

次のようなクエリを作成します。

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')

これを設定してデバッグする場合:

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

これにより、必要なクエリの最初の3行のみが生成されます。最後に「ON DUPLICATE KEY UPDATE」というテキストと別の配列値を追加するように拡張するにはどうすればよいですか?またはこれを行う別の方法がありますか?複数のクエリをsetQueryに追加したり、クエリを連結したりすることは可能ですか?

3
almost okey

_REPLACE INTO_クエリの作成は、_INSERT ... ON DUPLICATE KEY UPDATE_の作成と同じくらい簡単です。 _REPLACE INTO_ AND _ON DUPLICATE KEY UPDATE_ の間には違いがあることに注意してください。

コード:

_$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>";
_

これは構築されたクエリです:

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

これは[〜#〜] always [〜#〜]により、4つのエントリのバッチに対して影響を受ける同じ行数を出力します。

4行挿入しました



_ON DUPLICATE KEY UPDATE..._に関しては、これはJoomlaが生成したクエリの最後に句を追加し、 VALUES() syntax を含めるのと同じくらい簡単です。 (上記のスニペットの$db->setQuery()行のみreplace

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

このクエリを作成するには:

_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`)
_

このタイプのクエリは、動作が異なり、影響を受ける行に関して異なるフィードバックを提供します。

追加しようとするすべての行のデータベーステーブルに同一の行が存在する場合、_0_の影響を受ける行が表示されます。 PRIMARY IDが既に存在する場合-たとえば、1つの行がdateの値がクエリの値と異なる場合-_2_の影響を受ける行が表示されます(これを自分のローカルホストで実行し、私が読んだ他のことにもかかわらず、これは削除してから追加する必要があります)。したがって、この種の情報は、何を決定しようとしているかに応じて、非常に役立つか、非常に混乱する可能性があります。テーブルに4つのidがすべて表示されていて、4つの行のうち2つがdateの値を更新する必要があると想像してください。クエリの実行後、_4_行が影響を受けたことが通知されます。

これが 数年前にStackOverflowに投稿した関連する回答 です。

2
mickmackusa