INSERT IGNORE - все еще автоинкременты, альтернативный SQL-запрос? - PullRequest
2 голосов
/ 01 августа 2011
$q = $db->prepare('INSERT IGNORE INTO Cities (Name,Stamp) VALUES (?,?)');
$q->execute(array($city,$stamp));

Я использую этот код для вставки новых городов в таблицу городов. Я только заметил, что каждый запрос увеличивает поле id, и это не то, что я хочу. Не то, чтобы я полагался на значения id без пробелов, но смешно увеличивать их при каждом запуске кода.

Итак, какой умный SQL-запрос я могу запустить, чтобы дать мне ту же функциональность, не выполняя два запроса (сначала SELECT, затем INSERT), и это не auto_increment?

Описание таблицы:

    Field       Type         Null   Key Default Extra
    id          int(11)      NO     PRI NULL    auto_increment
    Name        varchar(100) YES    UNI NULL     
    countryid   int(11)      YES        NULL     
    Stamp       int(11)      YES        NULL     
    uid         int(11)      YES        NULL    

Код:

INSERT INTO Cities (Name,Stamp) VALUES (?,?) ON DUPLICATE KEY UPDATE Name = Name

увеличивает значение в моей таблице. Версия MySQL - 5.5.9. Ядром базы данных является innoDB.


Возможно, это может быть ошибка: http://bugs.mysql.com/bug.php?id=28781 Если вы прокрутите вниз до дна, вы увидите, что это все еще проблема, три года спустя ...

Ответы [ 3 ]

3 голосов
/ 01 августа 2011

См. Ошибка # 42497: пробелы в AUTO_INCREMENT V5.1 с InnoDB при использовании INSERT IGNORE (что на самом деле не является ошибкой).

Вам нужно либо настроить innodb_autoinc_lock_mode=0, либо изменить свое утверждение. Для получения дополнительной информации см. Соответствующую документацию AUTO_INCREMENT в InnoDB .

Это сводка поведения, которое вы видите. Новый метод для распределения значений автоинкремента в InnoDB был введен с MySQL 5.1.22:

Для операторов INSERT, в которых известно количество вставляемых строк. в начале обработки заявления InnoDB быстро выделяет необходимое количество значений автоинкремента без блокировки, но только если нет одновременного сеанса, уже удерживающего блокировка AUTO-INC на уровне таблицы (поскольку этот другой оператор будет выделение значений автоинкремента один за другим по мере прохождения). Больше точно, такой оператор INSERT получает значения автоинкремента под контролем мьютекса (легкий замок), который не проводится пока заявление не завершится, но только на время процесс распределения.

Короче говоря, MySQL может определить, сколько строк будет вставлено вашим оператором, и заранее назначает значение автоинкремента. Это предотвращает чередование нескольких одновременных операторов значений автоинкремента. Однако после того, как этот номер был выделен, его нельзя использовать снова. Это вводит возможность пробелов в значениях автоинкремента.

Следующий оператор работает для меня без увеличения значения автоинкремента и с innodb_autoinc_lock_mode = 1 (настройка по умолчанию):

INSERT INTO Cities (Name, Stamp)
SELECT $Name, $Stamp
  FROM Cities
 WHERE NOT EXISTS (
    SELECT NULL
      FROM Cities
     WHERE Name = $Name
);
0 голосов
/ 01 августа 2011

Имя или Штамп уникальны?

В противном случае значение увеличивается, поскольку вставляются одинаковые строки. Но я думаю, вы должны заметить, если в вашей таблице столько строк?

0 голосов
/ 01 августа 2011
$q = $db->prepare('INSERT INTO Cities (Name,Stamp) VALUES (?,?) ON DUPLICATE KEY UPDATE Name = Name');
$q->execute(array($city,$stamp));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...