mysql+事物插⼊,关于mysql:使⽤max()+1问题插⼊并设置
值
我正在尝试插⼊新⾏并使⽤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')
...我不断收到以下错误:
#1093 - You can't specify target table 'customers' for update in FROM clause
另外,如何停⽌同时添加2个不同的客户并且没有相同的customer_id?
您可以使⽤INSERT ... SELECT语句获取MAX()+1值并同时插⼊:
INSERT INTO
customers( customer_id, firstname, surname )
SELECT MAX( customer_id ) + 1, 'jim', 'sock' FROM customers;
注意:您需要从INSERT中删除VALUES,并确保选择的SELECT字段与声明的INSERT字段匹配。
这些查询完全在同⼀时间运⾏,可能会导致竞争状况。在此之前,您必须先lock table。
@xmedeko我以为1查询始终是原⼦查询,因此既然这⾥只有1 INSERT,那么它是原⼦操作且种族安全?
不,⾄少对于mysql没有。该查询确实选择然后插⼊。它们不是原⼦的。⽐赛条件有轻微的机会。
今天我学到了⼀些新东西。我以为在⼀个查询中执⾏所有操作时,不可能进⾏重复的查询,但是看,我错了。是时候重写⼀些东西以避免将来出现潜在问题了。
我有⼀个类似的场景,我可能要为此提出⼀个单独的SO问题。选择max()也是我⼀直在寻的⽅法,
但是在阅读了上⾯的评论之后,我开始质疑⾃⼰。在我的实例中,我有⼀个WHERE⼦句,该⼦句将返回的结果限制为特定的⼦集,因此我认为我在⽐赛条件下相对安全...对吗?
正确,您不能在同⼀查询的同⼀表中进⾏修改和选择。您将必须在两个单独的查询中执⾏上述操作。
最好的⽅法是使⽤事务,但是如果您不使⽤innodb表,那么最好的⽅法是锁定表并执⾏查询。所以:
Lock tables customers write;
$max = SELECT MAX( customer_id ) FROM customers;
抓住最⼤ID,然后执⾏插⼊
INSERT INTO customers( customer_id, firstname, surname )
VALUES ($max+1 , 'jim', 'sock')
unlock tables;
@RDL-我正在使⽤MyISAM,因此您的⽰例将正确运⾏,并允许同时使⽤不同的客户ID添加2个客户?谢谢
@Cozzy,正确。锁定表后,只有当前会话可以访问它。对该表的所有其他请求都将放⼊队列中,直到该表被解锁为⽌。因此,在同⼀时间添加记录不会发⽣重复。
如果没有要验证的customer_id列上的唯⼀键,就⽆法保证重复的值可以存在。此外,由于隔离级别的处理,可以为insert语句读取相同的最⼤值。为什么不使⽤本机AUTO_INCREMENT?
@RDL-我从第⼀个查询#1064中收到以下错误-您的SQL语法有错误;检查与您的MySQL服务器版本相对应的⼿册以获取正确的语法,以在第1⾏的客户附近使⽤@max = SELECT MAX(customer_id)
@Cozzy:您是否声明了@max变量?为什么您要使⽤这种⽅法会困扰您。
@OMG Ponies-原因是该表将包含修改前后的旧数据⾏。因此,您实际上可以看到谁和发⽣了什么变化。令我⼼烦意乱!也可以为此创建⼀个单独的表,并在删除之前将数据从⼀个表移动到另⼀个表。感谢您的所有帮助。
@Cozzy:我担⼼您的数据模型,如果您认为这是审计表的⽅法。
锁定表是⼀个繁重的过程...如果MAX查询中有⼀个WHERE,该怎么办?将INSERT INTO x (id_autoincremented, num, channel) VALUES (DEFAULT, IFNULL((SELECT MAX(num) FROM x WHERE channel = ?), 0)+1, ?)转换为INSERT INTO x (num, channel) (SELECT IFNULL((SELECT M
AX(num) FROM x WHERE channel = ?), 0)+1, ?)不会锁定表,⽽让其他INSERT⽤于其他channel,那么并发安全吗?
像这样对内部查询使⽤别名
INSERT INTO customers
( customer_id, firstname, surname )
VALUES
((SELECT MAX( customer_id )+1 FROM customers cust), 'sharath', 'rock')
@xmedeko这根本不是重复的。 EmCos的答案演⽰了⽤SELECT替换VALUES()的问题,⽽此答案则演⽰了如何将SELECT语句嵌套在VALUES()内(阅读EmCos答案的⼈可能会因为他的"注释"⽽认为不可能)
@Wipqozn你是对的,它不是重复的,但是应该在答案中提到不同之处。 另外,我对⽐赛条件的评论也适⽤于此答案。
insert into table1(id1) select (max(id1)+1) from table1;
不适⽤于MySQL,不允许在INSERT和SELECT⼦查询中使⽤相同的表。
为我⼯作mySQL ver 5.5.41
SELECT MAX(col) +1是不安全的-它不能确保您插⼊的客户不超过⼀个具有相同customer_id值的客户,⽆论是从同⼀张表中还是从其他任何表中进⾏选择。确保在插⼊MySQL中的表时分配唯⼀整数值??的正确⽅法是使⽤AUTO_INCREMENT。 ANSI标准是使⽤序列,但MySQL不⽀持它们。 AUTO_INCREMENT列只能在CREATE TABLE语句中定义:
就是说,这对我⽽⾔在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;
如何确保您选择多于⼀⾏?除⾮有group by,否则我⽆法想到使⽤max()的查询将返回多⾏的情况
他不是在谈论⽤max()检索多个⾏,⽽是正确地指出,通过使⽤max(customer_id)+ 1插⼊新客户,您不能确定id的唯⼀性。同时执⾏两个这样的语句将导致两个不同的客户具有相同的customer_id。
在⼦查询中使⽤表别名:
INSERT INTO customers
( customer_id, firstname, surname )
VALUES
((SELECT MAX( customer_id ) FROM customers C) +1, 'jim', 'sock')
我认为应该是: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;
关于答案均不适⽤于我的情况。我从这⾥得到了答案,我的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())
)
您⽆法在单个查询中执⾏此操作,但是可以在事务中执⾏。进⾏初始MAX()选择并锁定表,然后进⾏插⼊。事务确保没有任何事物会中断这两个查询,⽽锁确保没有其他事物可以尝试同时在其他地⽅进⾏相同的操作。
请您提供⼀个⽰例SQL查询吗?当使⽤事务和锁时,如果同时添加2个客户,或者简⽽⾔之,它会引发任何错误,是否只是将它们排队并⼀个接⼀个地运⾏?谢谢
实际上,您可以在单个语句中进⾏操作-⽆需事务。⽽且SELECT MAX不能确保始终返回唯⼀值-在⼏乎每个数据库上,默认隔离级别的读取查询优先于更新查询。
仅交易是不够的,您必须⾸先锁定表。
您的⼦查询只是不完整,仅此⽽已。请参阅以下有关我的瘾的查询:
INSERT INTO customers ( customer_id, firstname, surname )
VALUES ((SELECT MAX( customer_id ) FROM customers) +1), 'jim', 'sock')
mysql删除重复的数据保留一条这是选择来插⼊续集。
我正在尝试获取serial_no最⼤+1值及其正确的值。
SELECT MAX(serial_no)+1 into @var FROM sample.kettle;
Insert into kettle(serial_no,name,age,salary) values (@var,'aaa',23,2000);
我的是⼀个插⼊,但是这就是我最终在这⾥使⽤建议的结果。
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更新为相同的id。所以我不会⽤这个例⼦。
这是答案还是问题?
我们声明⼀个变量" a"
SET **@a** = (SELECT MAX( customer_id ) FROM customers) +1;
INSERT INTO customers
( customer_id, firstname, surname )
VALUES
(**@a**, 'jim', 'sock')
您可能应该在代码中添加更多注释。 这是否回答了两个问题? 为什么?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论