(免責事項:PostgreSQL初心者。)
OK、私が知る限り、私の機能は私が見たサンプルに適切に似ています。誰かが私がこれをどのように機能させるかについて私に手掛かりを与えることができますか?
create or replace function get_user_by_username(
username varchar(250),
online boolean
) returns setof record as $$
declare result record;
begin
if online then
update users
set last_activity = current_timestamp
where user_name = username;
end if;
return query
select
user_id,
user_name,
last_activity,
created,
email,
approved,
last_lockout,
last_login,
last_password_changed,
password_question,
comment
from
users
where
user_name = username
limit 1;
return;
end;
$$ language plpgsql;
setofレコードを返す関数を作成する場合は、selectステートメントで列タイプを定義する必要があります
クエリは次のようになります。
select * from get_user_by_username('Username', True) as
f(user_id integer, user_name varchar, last_activity, varchar, created date, email archar, approved boolean, last_lockout timestamp, last_login timestamp,
last_password_changed timestamp, password_question varchar, comment varchar)
(おそらくデータ型を変更する必要があります)
私は個人的に型アプローチを好みます。関数が編集された場合、すべてのクエリが正しい結果を返すことが保証されます。関数の引数を変更するたびに型も再作成/削除する必要があるため、苦痛になるかもしれません。
例えば:
CREATE TYPE return_type as
(user_id integer,
user_name varchar,
last_activity varchar,
created timestamp,
email varchar,
approved boolean,
last_lockout timestamp ,
last_login timestamp,
last_password_changed timestamp,
password_question varchar,
comment varchar);
create or replace function get_user_by_username( username varchar(250), online
boolean) returns setof return_type as $$
declare _rec return_type;
begin
if online then
update users
set last_activity = current_timestamp
where user_name = username;
end if;
for _rec in select
user_id,
user_name,
last_activity,
created,
email,
approved,
last_lockout,
last_login,
last_password_changed,
password_question,
comment
from
users
where
user_name = username
limit 1
loop
return next _rec;
end loop
end;
$$ language plpgsql;
_CREATE OR REPLACE FUNCTION get_user_by_username(_username text, _online bool)
RETURNS TABLE (
user_id int
,user_name text
,last_activity timestamp
, ... ) AS
$func$
BEGIN
IF _online THEN
RETURN QUERY
UPDATE users u
SET last_activity = current_timestamp
WHERE u.user_name = _username
RETURNING
u.user_id
,u.user_name
,u.last_activity
, ... ;
ELSE
RETURN QUERY
SELECT u.user_id
,u.user_name
,u.last_activity
, ...
FROM users u
WHERE u.user_name = _username;
END IF;
END
$func$ LANGUAGE plpgsql;
_
コール:
_SELECT * FROM get_user_by_username('myuser', TRUE)
_
_DECLARE result record;
_がありましたが、変数を使用しませんでした。クラフを削除しました。
レコードをUPDATE
から直接返すことができます。これは、追加のSELECT
ステートメントを呼び出すよりもはるかに高速です。 _RETURN QUERY
_および UPDATE
句を伴うRETURNING
を使用します。
ユーザーが__online
_でない場合、デフォルトはプレーンSELECT
になります。
関数内のクエリで列名(_tablename.columnname
_)をテーブル修飾しない場合、列名と名前付きパラメーターの間の命名の競合に注意してください。関数。
パラメータに位置参照(_$n
_)を使用することにより、このような競合を回避することもできます。または、neverアンダースコア(__username
_)のように列名に使用するプレフィックスを使用します。
_users.username
_がテーブルでniqueに定義されている場合、2番目のクエリの_LIMIT 1
_はただの問題です。
notの場合、UPDATE
は複数の行を更新できます。これは、おそらく間違ったです。
一意のusername
を想定して、クラフを削除しました。
関数の戻り値のタイプを定義します(@ertxの例のように)。そうしないと、すべての関数呼び出しで列定義リストを提供する必要があります。
(@ertxが提案するような)その目的のための型を作成することは有効なアプローチですが、おそらく単一の機能ではやり過ぎです。 _RETURNS TABLE
_ になる前に、それは古いバージョンのPostgreSQLに移行する方法でした-上記のように。
この単純な関数では、ループは必要ありません。
すべての関数には言語宣言が必要です。 _LANGUAGE plpgsql
_この場合。
パラメータの長さ制限(varchar(250)
)を定義しても意味がありません。 text
と入力するように簡略化しました。
テーブルusers
の-all columnsを返したい場合は、もっと簡単な方法があります。 PostgreSQLはすべてのテーブルに同じ名前の複合型を自動的に定義します。この場合、_RETURNS SETOF users
_を使用して、クエリを大幅に簡素化できます。
_CREATE OR REPLACE FUNCTION get_user_by_username(_username text, _online bool)
RETURNS SETOF users AS
$func$
BEGIN
IF _online THEN
RETURN QUERY
UPDATE users u
SET last_activity = current_timestamp
WHERE u.user_name = _username
RETURNING u.*;
ELSE
RETURN QUERY
SELECT *
FROM users u
WHERE u.user_name = _username;
END IF;
END
$func$ LANGUAGE plpgsql;
_
もっと「動的」なものが必要な場合は、以下を検討してください。