功能未返回预期值

时间:2013-12-23 21:45:16

标签: sql postgresql sql-update user-defined-functions plpgsql

我创建了一个函数,理论上应该在成功更改密码时返回true,而在相反的情况下则返回false。

该功能定义为:

CREATE OR REPLACE FUNCTION database."changePassword"(username character varying, newpassword character varying, oldpassword character varying) RETURNS boolean AS
$BODY$
UPDATE database.users SET hash = MD5($2) WHERE (username = $1 AND hash = MD5($3));
SELECT EXISTS(SELECT 1 FROM datsabase.users WHERE username = $1 AND hash = MD5($2))
$BODY$
LANGUAGE sql VOLATILE NOT LEAKPROOF
COST 100;

问题在于,当我调用像SELECT database."changePassword"('usrNm', 'newPassword', 'oldOne');这样的函数时,首先我得到了预期的真值,并且数据库中的值也发生了变化。

当我再次使用相同的参数调用该函数(并且一次又一次)时,它也返回true,但由于密码现在已更改且通过函数调用发送的旧密码不正确,因此不应该是这种情况。

我做错了吗?

PostgreSQL版本是9.3.1 我从pgAdmin接口调用了函数,从PHP脚本调用了同样的问题。

2 个答案:

答案 0 :(得分:2)

如果要返回是否已更改任何密码,可以在plpgsql函数中返回特殊变量FOUND,如下所示(使用@Pavel的输入进行简化):

CREATE OR REPLACE FUNCTION database."changePassword"(
    username character varying
   ,newpassword character varying
   ,oldpassword character varying
) RETURNS boolean AS
$func$
BEGIN

UPDATE database.users
SET    hash = MD5($2)
WHERE  username = $1
AND    hash = MD5($3);

RETURN FOUND;

END 
$func$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;

或者更简单,使用RETURNING子句。这也适用于普通的sql函数:

CREATE OR REPLACE FUNCTION database."changePassword"(
    username character varying
   ,newpassword character varying
   ,oldpassword character varying
) RETURNS boolean AS
$func$

UPDATE database.users
SET    hash = MD5($2)
WHERE  username = $1
AND    hash = MD5($3)
RETURNING TRUE;

$func$
LANGUAGE sql VOLATILE NOT LEAKPROOF;

如果没有更新行,则不返回任何内容。否则,你得到TRUE

答案 1 :(得分:1)

函数的返回值是SELECT语句的结果。当存储的用户哈希与第二个参数(newpassword)的哈希匹配时,结果为真。当密码更改为新密码时,此检查总是成功,并且函数对同一参数返回true,尽管update语句在第二次调用后不更新任何行。您应该更改逻辑,而不是查询匹配的用户和密码,检查天气是否更新了任何行。