插入并设置max()+ 1个问题的值

Coz*_*zzy 39 mysql sql insert mysql-error-1093

我正在尝试插入一个新行并使用max()+ 1设置customer_id.原因是该表已经在另一个名为id的列上具有auto_increatment,并且该表将具有多个具有相同customer_id的行.

有了这个:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers) +1, 'jim', 'sock')
Run Code Online (Sandbox Code Playgroud)

...我一直收到以下错误:

#1093 - You can't specify target table 'customers' for update in FROM clause
Run Code Online (Sandbox Code Playgroud)

另外,我如何阻止同时添加2个不同的客户而没有相同的customer_id?

EmC*_*mCo 73

您可以使用该INSERT ... SELECT语句获取MAX()+1值并同时插入:

INSERT INTO 
customers( customer_id, firstname, surname )
SELECT MAX( customer_id ) + 1, 'jim', 'sock' FROM customers;
Run Code Online (Sandbox Code Playgroud)

注意:您需要删除VALUESINSERT并确保SELECT所选字段匹配INSERT声明的字段.

  • 它可能导致竞争条件,这些查询同时运行.你必须在此之前"锁定表格". (2认同)
  • 不,至少对于mysql没有。该查询确实选择然后插入。它们不是原子的。比赛条件有轻微的机会。 (2认同)
  • 今天我学到了一些新东西。我以为在一个查询中执行所有操作时,不可能进行重复的查询,但是看,我错了。是时候重写一些东西以避免将来出现潜在问题了。 (2认同)

RDL*_*RDL 25

更正,您无法在同一查询中修改和选择同一个表.您必须在两个单独的查询中执行上述操作.

最好的方法是使用事务,但如果你不使用innodb表,那么接下来最好是锁定表然后执行查询.所以:

Lock tables customers write;

$max = SELECT MAX( customer_id ) FROM customers;
Run Code Online (Sandbox Code Playgroud)

抓住最大ID,然后执行插入

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

unlock tables;
Run Code Online (Sandbox Code Playgroud)


小智 10

像这样使用内部查询的别名

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id )+1 FROM customers cust), 'sharath', 'rock')
Run Code Online (Sandbox Code Playgroud)


OMG*_*ies 6

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`)
)
Run Code Online (Sandbox Code Playgroud)

也就是说,这对我来说在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;
Run Code Online (Sandbox Code Playgroud)


小智 6

insert into table1(id1) select (max(id1)+1) from table1;
Run Code Online (Sandbox Code Playgroud)


Gui*_*ult 5

在子查询中使用表别名:

INSERT INTO customers
  ( customer_id, firstname, surname )
VALUES 
  ((SELECT MAX( customer_id ) FROM customers C) +1, 'jim', 'sock')
Run Code Online (Sandbox Code Playgroud)

  • 我认为那将是:`INSERT INTO customers ( customer_id, firstname, surname )` `VALUES ((SELECT MAX( C.customer_id )` `FROM customers C) +1, 'jim', 'sock')` 但以下适用于我的安装 [mySQL ver 5.5.41]:`INSERT INTO table1(id1) SELECT (max(id1)+1) FROM table1;` (2认同)