Вставьте и установите значение с max () + 1 задач - PullRequest
37 голосов
/ 19 марта 2011

Я пытаюсь вставить новую строку и установить customer_id с max () + 1.Причиной этого является то, что в таблице уже есть auto_increatment для другого столбца с именем id, и в таблице будет несколько строк с одинаковым идентификатором customer_id.

При этом:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers) +1, 'jim', 'sock')

... Iпостоянно получаю следующую ошибку:

#1093 - You can't specify target table 'customers' for update in FROM clause

Кроме того, как бы я мог остановить одновременное добавление двух разных клиентов без одинакового идентификатора customer_id?

Ответы [ 11 ]

70 голосов
/ 19 марта 2011

Вы можете использовать оператор INSERT ... SELECT, чтобы получить значение MAX()+1 и вставить одновременно:

INSERT INTO 
customers( customer_id, firstname, surname )
SELECT MAX( customer_id ) + 1, 'jim', 'sock' FROM customers;

Примечание: Вам нужно удалить VALUES из INSERT и убедиться, что выбранные поля SELECT соответствуют объявленным INSERT полям.

25 голосов
/ 19 марта 2011

Правильно, вы не можете изменить и выбрать одну и ту же таблицу в одном запросе.Вы должны выполнить вышеуказанное в двух отдельных запросах.

Лучший способ - это использовать транзакцию, но если вы не используете таблицы innodb, тогда лучше всего будет заблокировать таблицы и затем выполнить ваши запросы.Итак:

Lock tables customers write;

$max = SELECT MAX( customer_id ) FROM customers;

Захватите максимальный идентификатор и затем выполните вставку

INSERT INTO customers( customer_id, firstname, surname )
VALUES ($max+1 , 'jim', 'sock')

unlock tables;
10 голосов
/ 25 апреля 2016

Использовать псевдоним для внутреннего запроса, как этот

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id )+1 FROM customers cust), 'sharath', 'rock')
6 голосов
/ 18 апреля 2012
insert into table1(id1) select (max(id1)+1) from table1;
5 голосов
/ 19 марта 2011

SELECT MAX(col) +1 небезопасно - это не гарантирует, что вы не вводите более одного клиента с одинаковым значением customer_id, независимо от того, выбираете ли вы из той же таблицы или из каких-либо других. Правильный способ гарантировать, что уникальное целочисленное значение будет назначено при вставке в вашу таблицу в MySQL, - это использовать AUTO_INCREMENT .Стандарт ANSI должен использовать последовательности, но MySQL не поддерживает их.Столбец AUTO_INCREMENT может быть определен только в операторе CREATE TABLE:

CREATE TABLE `customers` (
  `customer_id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(45) DEFAULT NULL,
  `surname` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`customer_id`)
)

Тем не менее, это работало нормально для меня на 5.1.49:

CREATE TABLE `customers` (
  `customer_id` int(11) NOT NULL DEFAULT '0',
  `firstname` varchar(45) DEFAULT NULL,
  `surname` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$

INSERT INTO customers VALUES (1, 'a', 'b');

INSERT INTO customers 
SELECT MAX(customer_id) + 1, 'jim', 'sock'
  FROM CUSTOMERS;
3 голосов
/ 03 октября 2014

Использовать псевдоним таблицы в подзапросе:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers C) +1, 'jim', 'sock')
2 голосов
/ 13 ноября 2017

Ни один из ответов на вопрос не работает для моего случая.Я получил ответ от здесь , и мой SQL:

INSERT INTO product (id, catalog_id, status_id, name, measure_unit_id, description, create_time)
VALUES (
  (SELECT id FROM (SELECT COALESCE(MAX(id),0)+1 AS id FROM product) AS temp),
  (SELECT id FROM product_catalog WHERE name="AppSys1"),
  (SELECT id FROM product_status WHERE name ="active"),
  "prod_name_x",
  (SELECT id FROM measure_unit WHERE name ="unit"),
  "prod_description_y",
  UNIX_TIMESTAMP(NOW())
)
1 голос
/ 19 марта 2011

Вы не можете сделать это в одном запросе, но вы можете сделать это в транзакции.Сделайте начальный выбор MAX () и заблокируйте таблицу, затем выполните вставку.Транзакция гарантирует, что ничто не прервет эти два запроса, а блокировка гарантирует, что больше никто не сможет попытаться сделать то же самое в другом месте одновременно.

0 голосов
/ 03 апреля 2019

Это выбрать и вставить продолжение.

Я пытаюсь получить серийный номер максимального значения +1 и дает правильное значение.

SELECT MAX(serial_no)+1 into @var FROM sample.kettle;
Insert into kettle(serial_no,name,age,salary) values (@var,'aaa',23,2000);
0 голосов
/ 14 ноября 2016

У меня есть вставка, но вот то, что я закончил, используя предложения здесь.

update
   m
set
   m.host_id = max(h.host_id)
from
   t_po_master as m
   inner join t_al_host_po_master as h on m.po_number = h.po_number
where
   m.host_id is NULL
   and m.client_code = '01'

РЕДАКТИРОВАТЬ - Это на самом деле не сработало.Я не уверен, почему нет, потому что превращение его в оператор выбора кажется, что оно будет работать, но это обновило все host_ids с тем же идентификатором.Так что я бы не стал использовать это хороший пример.

...