Trên khóa trùng lặp không làm gì cả


14

Tôi đang chèn vào bảng sau bằng LuaSQL với 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;

Bây giờ, vấn đề của tôi là, khi một người dùng (được đại diện bởi nick) cố gắng chèn lại cùng một yêu cầu, UNIQUEchỉ mục được kiểm tra và tập lệnh trả về sai. Điều này khiến tập lệnh của tôi bị lỗi và tôi phải khởi động lại tập lệnh.

Có điều gì tôi có thể làm trong INSERT ... ON DUPLICATE KEYlệnh để nó không làm gì hoặc ít nhất là KHÔNG trả về lỗi trong trường hợp DUPLICATE KEYkhông?

Nếu không, tôi sẽ phải cập nhật datedtrường của mình với DATETIMEgiá trị mới .

Câu trả lời:


23

Ba cách. Hoặc là IGNORElỗi trùng lặp:

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

hoặc cố gắng thực hiện cập nhật dự phòng khi có bản sao:

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

hoặc kiểm tra trùng lặp trước khi chèn:

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

Một sự khác biệt giữa cách thứ 3 và hai cách đầu tiên là khi có các bản sao, giá trị idsẽ không được tăng lên. Với INSERT IGNOREINSERT ... ON DUPLICATE KEY, nó sẽ được tự động tăng lên và vì việc chèn sẽ không được thực hiện, bạn sẽ có những khoảng trống trong các giá trị của id.

Tôi cũng nên thêm rằng các tập lệnh của bạn sẽ luôn luôn kiểm tra lỗi và không bị lỗi khi có. Bất kỳ truy vấn hoặc tuyên bố có thể thất bại và thỉnh thoảng trả lại lỗi, vì nhiều lý do. Các thủ thuật trên sẽ chỉ cứu bạn khỏi một loại lỗi.


1

Các tùy chọn là tuyệt vời, tôi chỉ biết một thứ tư. Bạn có thể Tạo một quy trình như sau (MySQL 5.5 trở lên).

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

Thật tuyệt, gần đây tôi không sử dụng MySQL nên tôi không biết điều đó. Bạn có thể cập nhật và giải thích về: điều gì xảy ra nếu xảy ra lỗi khác (không vi phạm khóa trùng lặp) không? Và làm thế nào để nó hoạt động chính xác (những gì 1062 đại diện cho)? Có phải truy vấn cần phải là một singe insert hoặc nó có thể hoạt động với việc chèn nhiều hàng không?
ypercubeᵀᴹ

1062 là hàng trùng lặp. Chỉ lỗi SQL này mới kích hoạt: SET v_dups = v_dups + 1;
billmask
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.