【问题标题】:Function not returning expected values函数未返回预期值
【发布时间】:2013-12-23 21:45:15
【问题描述】:

我创建了一个函数,理论上应该在密码更改成功时返回 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,并且数据库中的值发生了变化。

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

我做错了吗?

PostgreSQL 版本是 9.3.1。
我已经从 pgAdmin 界面和 PHP 脚本调用了该函数,同样的问题。

【问题讨论】:

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


    【解决方案1】:

    如果您想返回密码是否被更改,您可以在这样的 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

    【讨论】:

    • “FOUND”变量是布尔值,因此您可以简化代码 - 只需使用“RETURN FOUND”
    • @PavelStehule:当然!我通常不会错过这样一个简化的好机会。应用了。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2012-08-16
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      • 2012-01-21
      • 2018-12-05
      • 2018-12-05
      • 2013-09-04
      • 2016-02-13
      相关资源
      最近更新 更多