在一个UPDATE
查询中,是否可以SET
基于SQL查询结果的值?
这是我想到的查询不起作用:
UPDATE items SET itemcode=CONCAT('XYZ',(SELECT COUNT(*) as ctr FROM items
WHERE itemcode!=''),'GZ') WHERE itemid=123;
这不是实际查询,但是当我尝试运行两个连续查询时,使用一个查询的目的是防止竞争条件。
在items
表中插入记录后,我需要更新一些创建的项目并输入增量的项目代码。因此,它取决于表中具有空itemcode
的项目数。
答案 0 :(得分:2)
为了正确避免竞争条件,您可以使用LOCK TABLE
和交易以确保结果一致。
在您的查询中
UPDATE items SET itemcode=CONCAT('XYZ',(SELECT COUNT(*) as ctr FROM items
WHERE itemcode!=''),'GZ') WHERE itemid=123;
您正在从items
SELECT COUNT(*) as ctr FROM items WHERE itemcode!=''
然后将itemcode
123的itemid
与XYZGZ相关联。
您也可以使用UPDATE JOIN
和items
之间的ctr
:
UPDATE items JOIN (
SELECT CONCAT('XYZ', COUNT(*), 'GZ') AS newcode FROM items
WHERE itemcode!='') AS dummy
SET itemcode = dummy.newcode WHERE itemid = 123;
或者在MySQL中(并使用LOCK TABLES),您可以SELECT
将计数转换为临时变量,然后将itemcode
分配给该变量:
mysql> CREATE TABLE items ( itemid integer, itemcode varchar(32) );
mysql> INSERT INTO items VALUES ( 1, 'one' ), ( 2, 'two' ), ( 123, 'and 123');
mysql> LOCK TABLE items WRITE;
mysql> BEGIN WORK;
mysql> SELECT COUNT(*) INTO @x FROM items WHERE itemcode != '';
mysql> UPDATE items SET itemcode=CONCAT('XYZ',@x,'GZ') WHERE itemid = 123;
mysql> COMMIT WORK;
mysql> UNLOCK TABLES;
mysql> SELECT * FROM items;
+--------+----------+
| itemid | itemcode |
+--------+----------+
| 1 | one |
| 2 | two |
| 123 | XYZ3GZ |
+--------+----------+
3 rows in set (0.00 sec)
一种较短的做法,没有显式锁定:
mysql> BEGIN WORK;
mysql> SELECT COUNT(*) INTO @x FROM items WHERE itemcode != '' FOR UPDATE;
mysql> UPDATE items SET itemcode=CONCAT('XYZ',@x,'GZ') WHERE itemid = 123;
mysql> COMMIT WORK;
答案 1 :(得分:0)
这是您可能想要用于此案例的查询示例:
UPDATE
Table AS t
LEFT JOIN (
SELECT
Index1,
Index2,
COUNT(EventType) AS NumEvents
FROM
MEvents
WHERE
EventType = 'A' OR EventType = 'B'
GROUP BY
Index1,
Index2
) AS m ON
m.Index1 = t.Index1 AND
m.Index2 = t.Index2
SET
t.SpecialEventCount = m.NumEvents
WHERE
t.SpecialEventCount IS NULL
最初由@Hammerite here发布。
答案 2 :(得分:0)
子查询不应该在SET
部分内,因为我试图访问同一个表。问题中的查询返回以下错误:
#1093 – You can’t specify target table ‘items’ for update in FROM clause.
UPDATE items,(SELECT COUNT(*) as ctr FROM items WHERE itemcode!='') temp
SET itemcode=CONCAT('XYZ',temp.ctr+1,'GZ') WHERE itemid=123;