更新 2 列中的 1 列 - 取决于条件
Update 1 of 2 columns - depending on a condition
在 2 名玩家的游戏中,我试图通过调用以下存储函数来允许跳过玩家的回合:
CREATE OR REPLACE FUNCTION skip_game(
IN in_uid integer, -- player id
IN in_gid integer) -- game id
RETURNS void AS
$func$
BEGIN
UPDATE games
SET stamp1 = extract('epoch' from current_timestamp)
WHERE gid = in_gid
AND player1 = in_uid
AND stamp1 < stamp2; -- it is player1's turn
IF NOT FOUND THEN
UPDATE games
SET stamp2 = extract('epoch' from current_timestamp)
WHERE gid = in_gid
AND player2 = in_uid
AND stamp2 < stamp1; -- it is player2's turn
END IF;
END
$func$ LANGUAGE plpgsql;
是否可以将以上两个更新语句合并为一个 - 并根据条件将 stamp1
或 stamp2
设置为当前纪元时间?
此外,我不明白,为什么 PostgreSQL 9.5 总是报告 1 row
正在更新 - 如果我使用无效参数调用该函数会发生这种情况?
# select skip_game(1, 1);
skip_game
-----------------
(1 row)
# select skip_game(95, 95);
skip_game
-----------------
(1 row)
这是 games
table(我在 stamp
列中使用纪元整数,以便于与客户端的移动应用程序通信 - 使用 SQLite):
CREATE TABLE games (
gid SERIAL PRIMARY KEY,
created TIMESTAMP NOT NULL,
player1 INTEGER REFERENCES users(uid) ON DELETE CASCADE NOT NULL,
player2 INTEGER REFERENCES users(uid) ON DELETE CASCADE,
stamp1 INTEGER, -- timestamp of the last turn
stamp2 INTEGER, -- timestamp of the last turn
letters1 VARCHAR(7) NOT NULL,
letters2 VARCHAR(7) NOT NULL,
letters VARCHAR(116) NOT NULL,
board VARCHAR(225) NOT NULL,
style INTEGER NOT NULL CHECK (1 <= style AND style <= 4)
);
在查询中添加条件:
UPDATE games
SET stamp1 = CASE WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp) ELSE stamp1 END,
stamp2 = CASE WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp) ELSE stamp2 END
WHERE gid = in_gid
AND (player1 = in_uid OR player2 = in_uid);
使用单个 UPDATE
:
UPDATE games
SET stamp1 = CASE WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp)
ELSE stamp1 END
,stamp2 = CASE WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp)
ELSE stamp2 END
WHERE gid = in_gid AND (player1 = in_uid OR player2 = in_uid);
在 2 名玩家的游戏中,我试图通过调用以下存储函数来允许跳过玩家的回合:
CREATE OR REPLACE FUNCTION skip_game(
IN in_uid integer, -- player id
IN in_gid integer) -- game id
RETURNS void AS
$func$
BEGIN
UPDATE games
SET stamp1 = extract('epoch' from current_timestamp)
WHERE gid = in_gid
AND player1 = in_uid
AND stamp1 < stamp2; -- it is player1's turn
IF NOT FOUND THEN
UPDATE games
SET stamp2 = extract('epoch' from current_timestamp)
WHERE gid = in_gid
AND player2 = in_uid
AND stamp2 < stamp1; -- it is player2's turn
END IF;
END
$func$ LANGUAGE plpgsql;
是否可以将以上两个更新语句合并为一个 - 并根据条件将 stamp1
或 stamp2
设置为当前纪元时间?
此外,我不明白,为什么 PostgreSQL 9.5 总是报告 1 row
正在更新 - 如果我使用无效参数调用该函数会发生这种情况?
# select skip_game(1, 1);
skip_game
-----------------
(1 row)
# select skip_game(95, 95);
skip_game
-----------------
(1 row)
这是 games
table(我在 stamp
列中使用纪元整数,以便于与客户端的移动应用程序通信 - 使用 SQLite):
CREATE TABLE games (
gid SERIAL PRIMARY KEY,
created TIMESTAMP NOT NULL,
player1 INTEGER REFERENCES users(uid) ON DELETE CASCADE NOT NULL,
player2 INTEGER REFERENCES users(uid) ON DELETE CASCADE,
stamp1 INTEGER, -- timestamp of the last turn
stamp2 INTEGER, -- timestamp of the last turn
letters1 VARCHAR(7) NOT NULL,
letters2 VARCHAR(7) NOT NULL,
letters VARCHAR(116) NOT NULL,
board VARCHAR(225) NOT NULL,
style INTEGER NOT NULL CHECK (1 <= style AND style <= 4)
);
在查询中添加条件:
UPDATE games
SET stamp1 = CASE WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp) ELSE stamp1 END,
stamp2 = CASE WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp) ELSE stamp2 END
WHERE gid = in_gid
AND (player1 = in_uid OR player2 = in_uid);
使用单个 UPDATE
:
UPDATE games
SET stamp1 = CASE WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp)
ELSE stamp1 END
,stamp2 = CASE WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp)
ELSE stamp2 END
WHERE gid = in_gid AND (player1 = in_uid OR player2 = in_uid);