Pada kunci duplikat, jangan lakukan apa-apa

14

Saya memasukkan ke dalam tabel berikut menggunakan LuaSQL dengan PtokaX API.

CREATE TABLE `requests` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `ctg` VARCHAR(15) NOT NULL,
    `msg` VARCHAR(250) NOT NULL,
    `nick` VARCHAR(32) NOT NULL,
    `filled` ENUM('Y','N') NOT NULL DEFAULT 'N',
    `dated` DATETIME NOT NULL,
    `filldate` DATETIME NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `nick_msg` (`nick`, `msg`),
    UNIQUE INDEX `ctg_msg` (`ctg`, `msg`)
)
COMMENT='Requests from users in any of the categories.'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

Sekarang, masalah saya adalah, ketika pengguna (diwakili oleh nick) mencoba memasukkan permintaan yang sama lagi, UNIQUEindeks diperiksa dan skrip mengembalikan yang salah. Ini menyebabkan skrip saya gagal dan saya harus memulai ulang skrip.

Apakah ada sesuatu yang bisa saya lakukan dalam INSERT ... ON DUPLICATE KEYperintah sehingga tidak melakukan apa pun atau setidaknya TIDAK mengembalikan kesalahan jika terjadi DUPLICATE KEY?

Kalau tidak, saya harus pergi untuk memperbarui datedbidang saya dengan nilai baru DATETIME.

hjpotter92
sumber

Jawaban:

23

Tiga jalan. Salah satu IGNOREkesalahan duplikat:

INSERT IGNORE 
  ... ;                   -- without ON DUPLICATE KEY

atau coba lakukan pembaruan yang berlebihan ketika ada duplikat:

INSERT 
  ... 
ON DUPLICATE KEY UPDATE
  id = id ;

atau periksa duplikat sebelum memasukkan:

INSERT INTO requests
  (id, ctg, msg, nick, filled, dated, filldate)
SELECT
  NULL, 'urgent', 'Help!', 'Hermione', 'Y', NOW(), NOW()
FROM
  dual
WHERE NOT EXISTS
      ( SELECT *  FROM requests  WHERE (nick, msg) = ('Hermione', 'Help!') )
  AND NOT EXISTS
      ( SELECT *  FROM requests  WHERE (ctg, msg) = ('urgent', 'Help!') ) ;

Perbedaan antara cara ke-3 dan dua yang pertama adalah bahwa ketika ada duplikat, idtidak akan bertambah. Dengan INSERT IGNOREdan INSERT ... ON DUPLICATE KEY, itu akan bertambah secara otomatis dan karena penyisipan tidak akan dilakukan, Anda akan memiliki celah dalam nilai-nilai id.

Saya juga harus menambahkan bahwa skrip Anda harus selalu memeriksa kesalahan dan tidak gagal ketika ada. Permintaan atau pernyataan apa pun dapat gagal dan mengembalikan kesalahan sesekali, karena berbagai alasan. Trik di atas hanya akan menyelamatkan Anda dari satu jenis kesalahan.

ypercubeᵀᴹ
sumber
1

Pilihannya bagus, saya hanya tahu yang keempat. Anda dapat membuat prosedur sebagai berikut (MySQL 5.5 atau lebih tinggi).

DELIMITER ;;
CREATE PRODECURE...
...necessary parameters...
BEGIN

DECLARE v_dups BIGINT;
DECLARE CONTINUE HANDLER FOR 1062 SET v_dups = v_dups + 1;

-- RUN SIMPLE INSERT, IF IT TAKES DUPLICATE KEY NOTHING HAPPENS
END;;
billmask
sumber
Bagus, saya belum menggunakan MySQL belakangan ini jadi saya tidak tahu itu. Bisakah Anda memperbarui dan menguraikan: apa yang terjadi jika terjadi kesalahan (bukan duplikasi kunci) lainnya? Dan bagaimana cara kerjanya tepatnya (apa artinya 1062)? Apakah kueri harus berupa insert menghanguskan atau dapatkah ia bekerja dengan memasukkan beberapa baris?
ypercubeᵀᴹ
1062 adalah duplikat baris. Hanya kesalahan SQL ini yang memicu: SET v_dups = v_dups + 1;
billmask