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,这是您最初的问题。