На повторному ключі нічого не робити


14

Я вставляю в наступну таблицю за допомогою LuaSQL з API PtokaX.

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;

Тепер моя проблема полягає в тому, що коли користувач (представлений nick) намагається знову вставити той самий запит, UNIQUEіндекс перевіряється, а сценарій повертає помилкове. Це спричиняє збій мого сценарію, і мені доведеться перезапустити сценарій.

Чи можу я щось зробити в INSERT ... ON DUPLICATE KEYкоманді, щоб вона нічого не робила або, принаймні, НЕ повертала помилку у випадку DUPLICATE KEY?

Інакше мені доведеться піти на оновлення свого datedполя новим DATETIMEзначенням.

Відповіді:


23

Три способи. Або IGNOREповторювані помилки:

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

або спробуйте зробити надмірне оновлення, коли є дублікат:

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

або перевірити наявність дублікатів перед вставкою:

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

Різниця між 3-м способом та першими двома полягає в тому, що коли є дублікати, цей показник idне збільшуватиметься. З INSERT IGNOREі INSERT ... ON DUPLICATE KEY, він буде автоматично нарощений, і оскільки вставка не буде виконана, у вас будуть прогалини у значеннях id.

Я також повинен додати, що ваші сценарії завжди повинні перевіряти наявність помилок і не виходити з ладу, коли такі є. Будь-який запит чи заява може виходити з ладу і періодично повертати помилку з різних причин. Наведені вище прийоми позбавлять вас лише від одного виду помилок.


1

Варіанти чудові, я просто знаю четвертий. Ви можете створити процедуру наступним чином (MySQL 5.5 або вище).

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

Приємно, останнім часом я не використовую MySQL, тому не знав цього. Чи можете ви оновити та розробити: що станеться, якщо трапляються інші (не дублюючі порушення ключів) помилки? І як саме це працює (на що позначають 1062)? Чи повинен запит бути окремою вставкою чи він може працювати із вставкою декількох рядків?
ypercubeᵀᴹ

1062 - Дублюється рядок. Тільки ця помилка SQL запускає: SET v_dups = v_dups + 1;
законопроект
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.