Вставить и установить значение с max ()+1 проблем


Я пытаюсь вставить новую строку и установить 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')

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

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

Кроме того, как бы я остановил 2 разных клиента, добавляемых одновременно и не имеющих одного и того же customer_id?

10 33

10 ответов:

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

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

Lock tables customers write;

$max = SELECT MAX( customer_id ) FROM customers;

Возьмите max id и выполните команду insert

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

unlock tables;

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

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

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

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

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id )+1 FROM customers cust), 'sharath', 'rock')
insert into table1(id1) select (max(id1)+1) from table1;

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;

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

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

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

Ни один из ответов о не работает в моем случае. Я получил ответ от здесь, и мой 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())
)

Объявляем переменную ' a '

SET **@a** = (SELECT MAX( customer_id ) FROM customers) +1;

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  (**@a**, 'jim', 'sock')

Мой-это вставка, но вот то, что я закончил с использованием предложений здесь.

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'

EDIT-это на самом деле не сработало. Я не уверен, почему нет, так как превращение его в оператор select кажется, что он будет работать, но это обновило все идентификаторы host_id до одного и того же id. Так что я бы не стал использовать этот хороший пример.