tra-loi-cau-hoi-phat-trien-web.com

với chèn vào cập nhật khóa trùng lặp - cập nhật nhiều hàng cùng một lúc

Với phiên bản j Joomla mới nhất, tôi cố gắng đạt được một truy vấn vào cơ sở dữ liệu và cập nhật nhiều hàng cùng một lúc.

Tôi muốn thực hiện một truy vấn như thế này:

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

Nếu tôi thiết lập điều này và gỡ lỗi:

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

điều này chỉ tạo ra 3 hàng đầu tiên của truy vấn mong muốn của tôi. Làm cách nào tôi có thể mở rộng để thêm văn bản "TRÊN CẬP NHẬT TỪ KHÓA" và một giá trị mảng khác ở cuối? Hoặc có một cách khác để làm điều này? Có thể thêm nhiều truy vấn vào setQuery hoặc nối các truy vấn không?

3
almost okey

Xây dựng truy vấn REPLACE INTO Cũng đơn giản như xây dựng INSERT ... ON DUPLICATE KEY UPDATE. Lưu ý rằng có sự khác biệt giữa REPLACE INTOON DUPLICATE KEY UPDATE .

Mã số:

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

Đây là truy vấn được xây dựng:

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

Điều này sẽ [~ # ~] luôn luôn [~ # ~] in cùng số lượng hàng bị ảnh hưởng cho lô bốn mục của bạn:

4 hàng được chèn



Đối với ON DUPLICATE KEY UPDATE..., Điều này đơn giản như nối thêm mệnh đề vào cuối truy vấn do Joomla tạo và bao gồm VALUES() cú pháp . (chỉ thay thế dòng $db->setQuery() từ đoạn trích trên)

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

để tạo truy vấn này:

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

Loại truy vấn này hoạt động khác nhau và cung cấp phản hồi khác nhau về các hàng bị ảnh hưởng.

Khi các hàng giống hệt nhau tồn tại trong bảng cơ sở dữ liệu cho tất cả các hàng mà bạn định thêm, bạn sẽ thấy các hàng bị ảnh hưởng 0. Nếu ID PRIMARY đã tồn tại - giả sử 1 hàng có giá trị date khác với giá trị trong truy vấn - bạn sẽ thấy các hàng bị ảnh hưởng 2 (Tôi đã chạy nó trên localhost của riêng tôi và mặc dù những thứ khác tôi đã đọc, điều này phải được loại bỏ, sau đó thêm). Vì vậy, loại thông tin này có thể rất hữu ích hoặc rất khó hiểu tùy thuộc vào những gì bạn đang cố gắng xác định. Hãy tưởng tượng nếu bạn đã có tất cả bốn ids trong bảng của bạn và hai trong bốn hàng cần giá trị date để được cập nhật. Sau khi truy vấn được thực thi, bạn sẽ được thông báo rằng các hàng 4 Đã bị ảnh hưởng.

Đây là một câu trả lời có liên quan mà tôi đã đăng vài năm trước trên StackOverflow .

2
mickmackusa