MySQL检索SELECT检索的INSERT参数

时间:2014-02-27 20:26:00

标签: mysql

如果我有这样的表结构:

CREATE TABLE a (
  aid INT AUTO_INCREMENT,
  acol1 INT,
  acol2 INT,
  PRIMARY KEY(aid);
)

CREATE TABLE b (
  bid INT AUTO_INCREMENT,
  bcol INT,
  PRIMARY KEY(bid);
)

并运行声明:

`INSERT IN TO SET acol1 =(SELECT MAX(acol1)+ 1 as newMax FROM WHERE id =?)

在执行查询后,我是否还要检索newMax的值?我在PHP中寻找与last_insert_id()类似的东西,但在查询中寻找临时值。

显然,我试图在可能的情况下再次查询数据库。

编辑:

实际情况:

CREATE TABLE group (
  group_id INT AUTO_INCREMENT,
  PRIMARY KEY(group_id)
) ENGINE = MyISAM;

CREATE TABLE item (
  group_refid INT, --references group.group_id
  group_pos INT, --represents this item's position in its group
  text VARCHAR(4096), --data
  PRIMARY KEY(group_refid, group_pos)
) ENGINE = MyISAM;

所以问题是,当我向一个组添加一个新项目时,我需要创建它的

group_pos = MAX(group_pos) WHERE group_refid = ?

需要查询类似的内容:

INSERT INTO item (group_refid, group_pos) SET group_refid = 1, group_pos = (SELECT MAX(group_pos) + 1 FROM item WHERE group_refid = 1);

如您所知,此查询不起作用。对于特定的group_id,可能还没有项目条目的复杂性。

我试图将这一切都整合到一个原子声明中以防止竞争条件。

4 个答案:

答案 0 :(得分:1)

你不能。 insert query用于insering not selection。

您必须运行其他类似的查询

   SELECT MAX(acol1) + 1 as newMax FROM a WHERE acol2 = ?

了解更多read this

答案 1 :(得分:1)

我认为你可以做到:

INSERT INTO b
    SET bcol = (SELECT @acol := MAX(acol1) + 1 as newMax FROM a WHERE acol2 = ?);

然后,您可以使用变量@acol来获取所需的值。

编辑:

这是你想要的吗?

INSERT INTO item (group_refid, group_pos) 
    SELECT 1, MAX(group_pos) + 1
    FROM item
    WHERE group_refid = 1;

答案 2 :(得分:1)

INSERT INTO item (group_refid,group_pos) 
SELECT 1, (
   SELECT IFNULL(MAX(group_pos),0) + 1 
   FROM item 
   WHERE group_refid=1
);

但是,如果我们明确地谈论 MyISAM表,而不是另一个引擎,那么这将有效:

mysql> CREATE TABLE items (group_refid INT, group_pos INT AUTO_INCREMENT, PRIMARY KEY(group_refid,group_pos)) ENGINE=MyISAM;
Query OK, 0 rows affected (0.12 sec)

mysql> INSERT INTO items (group_refid) VALUES (1),(2),(1),(1),(2),(4),(2),(1);
Query OK, 8 rows affected (0.02 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM items ORDER BY group_refid, group_pos;
+-------------+-----------+
| group_refid | group_pos |
+-------------+-----------+
|           1 |         1 |
|           1 |         2 |
|           1 |         3 |
|           1 |         4 |
|           2 |         1 |
|           2 |         2 |
|           2 |         3 |
|           4 |         1 |
+-------------+-----------+

但是,PK中第二列的AUTO_INCREMENT 无法移植到另一个数据库引擎

答案 3 :(得分:0)

不直接在声明中,没有。您需要一个单独的语句来检索值。

但是,您可以将SELECT中的值“捕获”到用户定义的变量中,然后使用SELECT(在同一个数据库会话中)检索它,如果您需要“知道”从SELECT返回的值

例如:

INSERT INTO b (bcol) 
SELECT @bcol := (MAX(a.acol1) + 1) AS newMax
  FROM a WHERE a.acol2 = ?)

SELECT @bcol + 0 AS new_bcol

注:

请注意,select中分配的用户定义变量可能会在会话的其他位置进行修改,例如,它可能会被执行定义INSERT目标表的触发器覆盖。

作为边缘情况,不是任何人都会这样做,但也有可能在插入之前可能有一个BEFORE INSERT触发器修改bcol的值。因此,如果您需要“知道”实际插入的值,那么可以在AFTER INSERT触发器中使用。您可以在该触发器中的用户定义变量中捕获它。

针对a表运行第二个单独的查询受竞争条件的影响,这是另一个会话插入/更新/删除表a中的行的小机会窗口,例如第二个查询可能返回与第一个查询不同的值...它可能不是第一次检索的值。当然,除非您处于具有REPEATABLE READ隔离级别的InnoDB事务的上下文中,否则您已实现了一些并发锁定策略。