更新存储过程中的 table 记录和 return 该记录的 ID
Update table record in stored procedure and return the id of that record
在 2 位玩家的 Android 文字游戏中 -
游戏数据保存在以下table:
# desc games;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| gid | int(11) | NO | PRI | NULL | auto_increment |
| created | int(11) | NO | | NULL | |
| player1 | int(11) | YES | | NULL | |
| player2 | int(11) | YES | | NULL | |
| stamp1 | int(11) | NO | | NULL | |
| stamp2 | int(11) | NO | | NULL | |
| letters1 | varchar(7) | NO | | NULL | |
| letters2 | varchar(7) | NO | | NULL | |
| letters | varchar(116) | NO | | NULL | |
| board | varchar(225) | NO | | NULL | |
| style | int(11) | NO | | 0 | |
+----------+--------------+------+-----+---------+----------------+
player1 和 player2 列保留了一场比赛中对方玩家的 2 个不同数字 ID。
stamp1 和 stamp2 是最后一步的时间戳(最初为 0)。
我正在尝试编写一个 stored procedure,它将带一个玩家 uid 并加入一个只有 1 个其他玩家的空游戏,或者从头开始创建一个新游戏。
一个特殊情况是:如果已经有玩家 uid 的新游戏并且她还没有执行任何动作(即 stamp1 是 0),然后我只是 return 该游戏的 gid(而不是创建另一个新游戏)。
delimiter $$$
drop procedure if exists find_game;
create procedure find_game(IN uid integer,
IN letters1 varchar(7),
IN letters2 varchar(7),
IN letters varchar(116),
OUT gid integer)
begin
start transaction;
/* maybe there is a new game already, just waiting for the player's 1st move*/
select gid into @gid from games where (player1 = uid and stamp1 = 0) or (player2 = uid and stamp2 = 0) limit 1;
IF found_rows() = 0 THEN
/* try to find games having just 1 player (with different uid) */
update games set player2 = uid where player1 != uid and stamp1 > 0 and player2 = null;
IF row_count() = 0 THEN
/* create new game with player1 = uid and stamp1 = 0*/
insert into games (created, player1, stamp1, stamp2, letters1, letters2, letters, board, style)
values (unix_timestamp(), uid, 0, 0, letters1, letters2, letters, space(225), 1);
ELSE
/* how to find the gid of the updated record? */
END IF;
END IF;
commit;
end
$$$
不幸的是,上面的代码有两个问题。
1) 如果我评论除上面第一个 select 语句之外的所有内容 - 我在 [=50 中得到 null =]gid,而当我 运行 在 mysql 提示时它按预期工作:
# select gid from games where (player1 = 1 and stamp1 = 0) or (player2 = 1 and stamp2 = 0);
+-----+
| gid |
+-----+
| 1 |
| 2 |
| 3 |
+-----+
2)请指教,如何在上述row_count() > 0
的情况下找到更新游戏的gid。或者有更好的方法吗?
更新
我听从了 Juan Carlos 的建议(谢谢!),我尝试使用以下代码首先 select 然后 update:
delimiter $$$
drop procedure if exists find_game;
create procedure find_game(IN uid integer,
IN letters1 varchar(7),
IN letters2 varchar(7),
IN letters varchar(116),
OUT gid integer)
begin
start transaction;
/* maybe there is a new game already, just waiting for the player's 1st move*/
select gid into @gid from games
where (player1 = uid and stamp1 = 0) or (player2 = uid and stamp2 = 0) limit 1;
IF select found_rows() = 0 THEN
/* try to find games having just 1 player (with different uid) */
select gid into @gid from games
where (player1 != uid and stamp1 > 0 and player2 is null) limit 1;
IF select found_rows() > 0 THEN
update games set player2 = uid where gid = @gid;
ELSE
/* create new game with player1 = uid and stamp1 = 0*/
insert into games (created, player1, stamp1, stamp2, letters1, letters2, letters, board, style)
values (unix_timestamp(), uid, 0, 0, letters1, letters2, letters, space(225), 1);
select last_insert_id() into @gid;
END IF;
END IF;
commit;
end
$$$
不幸的是,我收到语法错误:
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server
version for the right syntax to use near
'select found_rows() = 0 THEN
select gid into @g' at line 13
如果你已经有这个,但是如果玩家已经在一个全新的游戏中,这会发现。
select gid into @gid
from games
where (player1 != uid and stamp1 = 0)
or (player2 = uid and stamp2 = 0) limit 1;
为什么不使用类似的东西更改您的更新,您可以在其中寻找有空位的游戏。
select gid into @gid
from games
where (player1 != uid and stamp1 > 0 and player2 is null);
update games set player2 = uid where gid = @gid
注意: 为什么要搜索 stamp1 > 0
??您的插入创建了 stamp1 = 0
的新游戏,您的更新不会找到仅 1 player
的游戏
在 2 位玩家的 Android 文字游戏中 -
游戏数据保存在以下table:
# desc games;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| gid | int(11) | NO | PRI | NULL | auto_increment |
| created | int(11) | NO | | NULL | |
| player1 | int(11) | YES | | NULL | |
| player2 | int(11) | YES | | NULL | |
| stamp1 | int(11) | NO | | NULL | |
| stamp2 | int(11) | NO | | NULL | |
| letters1 | varchar(7) | NO | | NULL | |
| letters2 | varchar(7) | NO | | NULL | |
| letters | varchar(116) | NO | | NULL | |
| board | varchar(225) | NO | | NULL | |
| style | int(11) | NO | | 0 | |
+----------+--------------+------+-----+---------+----------------+
player1 和 player2 列保留了一场比赛中对方玩家的 2 个不同数字 ID。
stamp1 和 stamp2 是最后一步的时间戳(最初为 0)。
我正在尝试编写一个 stored procedure,它将带一个玩家 uid 并加入一个只有 1 个其他玩家的空游戏,或者从头开始创建一个新游戏。
一个特殊情况是:如果已经有玩家 uid 的新游戏并且她还没有执行任何动作(即 stamp1 是 0),然后我只是 return 该游戏的 gid(而不是创建另一个新游戏)。
delimiter $$$
drop procedure if exists find_game;
create procedure find_game(IN uid integer,
IN letters1 varchar(7),
IN letters2 varchar(7),
IN letters varchar(116),
OUT gid integer)
begin
start transaction;
/* maybe there is a new game already, just waiting for the player's 1st move*/
select gid into @gid from games where (player1 = uid and stamp1 = 0) or (player2 = uid and stamp2 = 0) limit 1;
IF found_rows() = 0 THEN
/* try to find games having just 1 player (with different uid) */
update games set player2 = uid where player1 != uid and stamp1 > 0 and player2 = null;
IF row_count() = 0 THEN
/* create new game with player1 = uid and stamp1 = 0*/
insert into games (created, player1, stamp1, stamp2, letters1, letters2, letters, board, style)
values (unix_timestamp(), uid, 0, 0, letters1, letters2, letters, space(225), 1);
ELSE
/* how to find the gid of the updated record? */
END IF;
END IF;
commit;
end
$$$
不幸的是,上面的代码有两个问题。
1) 如果我评论除上面第一个 select 语句之外的所有内容 - 我在 [=50 中得到 null =]gid,而当我 运行 在 mysql 提示时它按预期工作:
# select gid from games where (player1 = 1 and stamp1 = 0) or (player2 = 1 and stamp2 = 0);
+-----+
| gid |
+-----+
| 1 |
| 2 |
| 3 |
+-----+
2)请指教,如何在上述row_count() > 0
的情况下找到更新游戏的gid。或者有更好的方法吗?
更新
我听从了 Juan Carlos 的建议(谢谢!),我尝试使用以下代码首先 select 然后 update:
delimiter $$$
drop procedure if exists find_game;
create procedure find_game(IN uid integer,
IN letters1 varchar(7),
IN letters2 varchar(7),
IN letters varchar(116),
OUT gid integer)
begin
start transaction;
/* maybe there is a new game already, just waiting for the player's 1st move*/
select gid into @gid from games
where (player1 = uid and stamp1 = 0) or (player2 = uid and stamp2 = 0) limit 1;
IF select found_rows() = 0 THEN
/* try to find games having just 1 player (with different uid) */
select gid into @gid from games
where (player1 != uid and stamp1 > 0 and player2 is null) limit 1;
IF select found_rows() > 0 THEN
update games set player2 = uid where gid = @gid;
ELSE
/* create new game with player1 = uid and stamp1 = 0*/
insert into games (created, player1, stamp1, stamp2, letters1, letters2, letters, board, style)
values (unix_timestamp(), uid, 0, 0, letters1, letters2, letters, space(225), 1);
select last_insert_id() into @gid;
END IF;
END IF;
commit;
end
$$$
不幸的是,我收到语法错误:
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server
version for the right syntax to use near
'select found_rows() = 0 THEN
select gid into @g' at line 13
如果你已经有这个,但是如果玩家已经在一个全新的游戏中,这会发现。
select gid into @gid
from games
where (player1 != uid and stamp1 = 0)
or (player2 = uid and stamp2 = 0) limit 1;
为什么不使用类似的东西更改您的更新,您可以在其中寻找有空位的游戏。
select gid into @gid
from games
where (player1 != uid and stamp1 > 0 and player2 is null);
update games set player2 = uid where gid = @gid
注意: 为什么要搜索 stamp1 > 0
??您的插入创建了 stamp1 = 0
的新游戏,您的更新不会找到仅 1 player