selectクエリを実行し、行が更新されている場合はその結果を返してくれるplpgsqlプロシージャを作成したいと思います。plpgsqlはそれを返す前にクエリを処理します
私は、SELECT nickname FROM use_session_token(...)
で通常のクエリのようにプロシージャコールを処理できるようにしたいと思います。
通常私はRETURN QUERY(...)
を使用しますが、私は最初の行を更新する(token
が主な指標であるので、それが1またはnoneのいずれかです)
しかし、実際には、私は他の基準が満たされた場合、行のみが返され、更新したいです、私は主キーそのものを操作することはできません。
私はRefcursor
を使用し、もう1つはSELECT INTO
を使用して2回試みましたが、実際にはSETOF users
を返しません。
SELECT INTO
と私の試み:cursor
と
CREATE OR REPLACE FUNCTION use_session_token(Char(128), Inet) RETURNS SETOF users AS $$
DECLARE
row Record;
BEGIN
SELECT u.* INTO row FROM sessions AS t
INNER JOIN users AS u ON (t.user_id = u.id)
WHERE
t.token=$1 AND
t.date_last_used > NOW() - interval '30 minutes' AND
t.ip_address=$2 AND
u.is_deleted=FALSE AND
EXISTS(
SELECT 1 FROM mail AS m
WHERE m.user_id=u.id AND m.is_confirmed=TRUE AND m.is_deleted=FALSE
)
;
IF (row) THEN
UPDATE sessions SET date_last_used=NOW() WHERE token=$1;
ELSE
-- maybe do other things if there is no result
END IF;
RETURN row;
END;
$$ LANGUAGE 'plpgsql';
私の試み:
CREATE OR REPLACE FUNCTION use_session_token(Char(128), Inet) RETURNS SETOF users AS $$
DECLARE
cursor Refcursor;
row Record;
BEGIN
OPEN cursor SCROLL FOR (
SELECT u.* INTO row FROM sessions AS t
INNER JOIN users AS u ON (t.user_id = u.id)
WHERE
t.token=$1 AND
t.date_last_used > NOW() - interval '30 minutes' AND
t.ip_address=$2 AND
u.is_deleted=FALSE AND
EXISTS(
SELECT 1 FROM mail AS m
WHERE m.user_id=u.id AND m.is_confirmed=TRUE AND m.is_deleted=FALSE
)
);
FETCH cursor INTO row;
IF (FOUND) THEN
MOVE PRIOR cursor;
UPDATE sessions SET date_last_used=NOW() WHERE CURRENT OF cursor;
ELSE
-- maybe do other things if there is no result
END IF;
RETURN row;
END;
$$ LANGUAGE 'plpgsql';
しかし、両方の試みは実際に私は、適切な結果セットを返すことが本当にできないんだということで失敗。
これを達成し、私の問題を解決する最良の方法は何ですか?
両方の試みのどちらが優れているのですか(または3番目の解決策ですか)?
ありがとう、あなたの答えは本当に私を助けてくれました。関数でレコードが必要ないので、実際には 'RETURN QUERY SELECT ... 'で解決しました。私はRETURNが手順を終了しないことを知らなかった。しかしメモ:それは 'RETURN QUERY ...'であり、 'RETURN QUERY ... 'ではありません。後者は文法エラー – h345k34cr
を助けてくれて、エラーを指摘してくれてありがとう。回答が修正されました。 'RETURN'は実際に関数を終了します。データを返さないだけです。そのためには' RETURN NEXT'または 'RETURN QUERY'が必要です。 – Patrick