Вставить и установить значение с 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 ответов:
Правильно, вы не можете изменить и выбрать из той же таблицы в том же запросе. Вам придется выполнить все вышесказанное в двух отдельных запросах.
Лучший способ-использовать транзакцию, но если вы не используете 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')
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. Так что я бы не стал использовать этот хороший пример.