Jer*_*acs 36 postgresql plpgsql
(免责声明:PostgreSQL新手.)
好吧,据我所知,我的功能与我见过的样本非常相似.有人能否告诉我如何让这个工作?
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;
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 41
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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT * FROM get_user_by_username('myuser', TRUE)
Run Code Online (Sandbox Code Playgroud)
你有,DECLARE result record;
但没有使用变量.我删除了残骸.
您可以直接从中返回记录UPDATE
,这比调用其他SELECT
语句要快得多.使用RETURN QUERY
和UPDATE
使用RETURNING
条款.
如果用户不是_online
,则默认为普通SELECT
.
如果您没有tablename.columnname
对函数内的查询中的列名()进行表限定,请注意列名和命名参数之间的命名冲突,这些参数在函数内的任何位置都是可见的(大多数).
您还可以通过$n
对参数使用位置引用()来避免此类冲突.或者使用从不用于列名的前缀:如下划线(_username
).
如果在您的表中users.username
定义了唯一,那么LIMIT 1
在第二个查询中只是愚蠢的.
如果不是,则UPDATE
可以更新多行,这很可能是错误的.
我假设一个独特的username
并删除了残酷.
定义函数的返回类型(如@ertx演示)或者您必须在每个函数调用中提供列定义列表,这很尴尬.
为此目的创建类型(如@ertx提议)是一种有效的方法,但对于单个函数可能过度.这是在我们RETURNS TABLE
为此目的之前使用旧版PostgreSQL的方法- 如上所示.
你并不需要一个循环为这个简单的功能.
每个函数都需要语言声明.LANGUAGE plpgsql
在这种情况下.
定义varchar(250)
参数的长度限制()可能没有意义.我简化了打字text
.
如果要返回表的所有列users
,则有一种更简单的方法.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;
Run Code Online (Sandbox Code Playgroud)
如果您需要更"动态"的东西,请考虑:
ert*_*rtx 30
如果要创建函数返回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)
Run Code Online (Sandbox Code Playgroud)
(您可能需要更改数据类型)
我个人更喜欢类型方法.它确保如果编辑该函数,所有查询将返回正确的结果.这可能是一种痛苦,因为每次修改函数的参数时,您都需要重新创建/删除类型.
例如:
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;
Run Code Online (Sandbox Code Playgroud)