Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何确保存储函数始终返回TRUE或FALSE?_Postgresql_Stored Procedures_Plpgsql_Coalesce_Postgresql 9.5 - Fatal编程技术网

Postgresql 如何确保存储函数始终返回TRUE或FALSE?

Postgresql 如何确保存储函数始终返回TRUE或FALSE?,postgresql,stored-procedures,plpgsql,coalesce,postgresql-9.5,Postgresql,Stored Procedures,Plpgsql,Coalesce,Postgresql 9.5,使用以下存储函数,我希望验证用户数据: CREATE OR REPLACE FUNCTION check_user( in_social integer, in_sid varchar(255), in_auth varchar(32)) RETURNS boolean AS $func$ SELECT MD5('secret word' || in_social || in_sid) = in_auth; $fun

使用以下存储函数,我希望验证用户数据:

CREATE OR REPLACE FUNCTION check_user(
        in_social integer,
        in_sid varchar(255),
        in_auth varchar(32))
        RETURNS boolean AS
$func$
        SELECT MD5('secret word' || in_social || in_sid) = in_auth;
$func$ LANGUAGE sql IMMUTABLE;
我将在循环另一个存储函数中的JSON对象数组时调用它,如果它为任何JSON对象返回
FALSE
(从而回滚整个事务),则将
引发异常

我没有在这里转储第二个存储函数的源代码,而是在下面准备了3个简单的测试函数-

CREATE OR REPLACE FUNCTION test1() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user1', '56db1046fa7b664c9b3d05bf7413552a') THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
第一个功能按预期工作并打印
有效用户

CREATE OR REPLACE FUNCTION test2() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user2', '56db1046fa7b664c9b3d05bf7413552a') THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION test3() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user1', NULL) THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
第二个功能按预期工作并打印
无效用户

CREATE OR REPLACE FUNCTION test2() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user2', '56db1046fa7b664c9b3d05bf7413552a') THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION test3() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user1', NULL) THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
第三个功能无法按预期工作并打印
有效用户

CREATE OR REPLACE FUNCTION test2() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user2', '56db1046fa7b664c9b3d05bf7413552a') THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION test3() RETURNS void AS
$func$
BEGIN
        IF NOT check_user(42, 'user1', NULL) THEN
                RAISE NOTICE 'invalid user';
        ELSE
                RAISE NOTICE 'valid user';
        END IF;
END
$func$ LANGUAGE plpgsql;
这是因为
check\u user()
返回
NULL
而不是布尔值


COALESCE
可以围绕
check\u user()
调用
IF
-statement。。。但是有没有更好的方法来解决这个问题呢?

我会在check_user()函数中添加coalesce,这样它总是返回true或false

    SELECT MD5('secret word' || in_social || in_sid) = coalesce(in_auth,'');
如果其他值也可能为空,甚至可以使用下面的选项:

    SELECT MD5('secret word' || coalesce(in_social,-1)::varchar || coalesce(in_sid,'')) = coalesce(in_auth,'');
存在“-1”一个永远不会在社交中分配的值

但请注意,如果双方的计算结果均为
null
,则比较结果将返回
true

if check_user(42, 'user1', null) is not true then raise notice 'invalid user';
对于非空输入,与运算符相同。但是,如果两个输入都为null,则返回false;如果只有一个输入为null,则返回true。类似地,对于非空输入,IS NOT DISTINCT to IS identified to=与IS-idential to=不同,但当两个输入都为空时,它返回true;当只有一个输入为空时,它返回false。因此,这些构造有效地起作用,就好像null是一个正常的数据值,而不是“未知的”

更简单的方法是只声明函数并将返回值与
不为真进行比较

if check_user(42, 'user1', null) is not true then raise notice 'invalid user';
STRICT表示每当函数的任何参数为null时,该函数总是返回null。如果指定了此参数,则当存在空参数时,不执行该函数;相反,将自动假定为空结果


这还可以避免执行函数的任何成本。

这是我可能会用到的,因为函数与安全相关,因此我不想记住任何边缘情况(例如,如果check_user(…)不正确,则在声明为
STRICT
时强制使用
)将来使用它的时候-

CREATE OR REPLACE FUNCTION check_user(
        in_social integer, 
        in_sid varchar(255), 
        in_auth varchar(32))
        RETURNS boolean AS
$func$
        SELECT CASE 
                WHEN in_social IS NULL THEN FALSE
                WHEN in_sid    IS NULL THEN FALSE
                WHEN in_auth   IS NULL THEN FALSE
                ELSE (MD5('secret word' || in_social || in_sid) = in_auth)
        END;

$func$ LANGUAGE sql IMMUTABLE;

在第二条语句中(对于
STRICT
函数),是否必须使用
is not true
部分?我不能只使用
吗?如果不检查用户(42,'user1',null),则发出通知“无效用户”;如果结束?感谢you@AlexanderFarber:
expression is not true
将为
false
null
返回true,而
not expression
只为
false
返回
true
而不为
null
返回true,这是您最初的问题。