Len*_*enB 8 postgresql null row plpgsql
我有一个函数registration()
,它应该在某些情况下向表添加一行.我已经包含了一段代码和来自通话的输出.
如果select *
返回一个非空表行(它根据它执行RAISE NOTICE
),我想引发异常而不添加行.该示例似乎表明它rowt
不是null,但仍然rowt IS NOT NULL
返回f
(并且不会引发异常).
我希望这是我看不到的小事.
select * into rowt from Email where email_email = eml;
RAISE NOTICE '%, rowt IS NOT NULL:%',rowt, rowt IS NOT NULL;
if rowt IS NOT NULL THEN
RAISE EXCEPTION 'email address, %, already registered.' , eml;
END IF;
Run Code Online (Sandbox Code Playgroud)
输出:
NOTICE: (7,,,), rowt IS NOT NULL:f
registration
--------------
21
(1 row)
CREATE TABLE IF NOT EXISTS Email (
email_email VARCHAR(50) NOT NULL,
email_password VARCHAR(50) NOT NULL,
email_id integer DEFAULT nextval('email_email_id_seq'::regclass) NOT NULL,
email_person_id integer
);
CREATE OR REPLACE FUNCTION registration( wr text ) RETURNS integer AS $rL$
DECLARE
eml text;
pwd text;
nm text;
rle text;
emid integer;
rowt Email%ROWTYPE;
BEGIN
eml := getWebVarValue( wr , 'email' );
select * into rowt from Email where email_email = eml;
RAISE NOTICE '%, rowt IS NOT NULL:%', rowt, rowt IS NOT NULL;
IF rowt IS NOT NULL THEN
RAISE EXCEPTION 'email address, %, already registered.' , eml;
END IF;
pwd := getWebVarValue( wr , 'password' );
IF pwd IS NULL THEN
RAISE EXCEPTION 'No password specified in registration.';
END IF;
INSERT INTO Email VALUES (eml,pwd) RETURNING Email.email_id INTO emid;
--nm = getWebVarValue( wr , 'name' );
--rle = getWebVarValue( wr , 'role' );
RETURN emid;
END;
$rL$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 11
正如@Pavel提供的那样,检查<row-type> IS NOT NULL
不会像您期望的那样工作.它返回TRUE
if(且仅当)每个列都是NOT NULL.
CREATE OR REPLACE FUNCTION registration(wr text)
RETURNS integer AS
$rL$
...
SELECT * INTO rowt FROM email WHERE email_email = eml;
IF FOUND THEN
RAISE EXCEPTION 'email address, %, already registered.', eml;
END IF;
...
$rL$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
或者你可以在测试中反转你的表达.
IF rowt IS NULL THEN
-- do nothing
ELSE
RAISE EXCEPTION 'email address, %, already registered.' , eml;
END IF;
Run Code Online (Sandbox Code Playgroud)
您找到的任何现有行至少包含一列FOUND
,因此NOT NULL
只有在找不到任何内容时才会返回rowt IS NULL
.
相关答案更多细节:
针对ROW类型的NULL测试是特定的:
postgres=# SELECT r, r IS NULL AS "is null", r IS NOT NULL AS "is not null"
FROM (VALUES(NULL,NULL),
(10, NULL),
(10,10)) r ;
r | is null | is not null
---------+----------+--------------
(,) | t | f
(10,) | f | f
(10,10) | f | t
(3 rows)
Run Code Online (Sandbox Code Playgroud)
因此,NOT NULL
仅当所有字段都不为null时,才返回true。
从您的代码可以看出,您希望通过将电子邮件地址插入表中来注册该地址,但前提是该电子邮件地址尚未注册并且提供了密码。对于初学者,您应该更改表定义以反映这些要求:
CREATE TABLE email (
id serial PRIMARY KEY,
addr varchar(50) UNIQUE NOT NULL,
passw varchar(50) NOT NULL,
person_id integer
);
Run Code Online (Sandbox Code Playgroud)
的UNIQUE
限制addr
意味着 PG 不允许重复的电子邮件地址,因此您不必对此进行测试。您应该在执行插入时测试唯一的违规行为。
对于该函数,我建议您传入电子邮件地址和密码,而不是将业务逻辑放在函数内。像这样,该函数具有较少的依赖性,并且可以更轻松地在其他上下文中重用(例如通过网络应用程序通过其他方式注册电子邮件地址)。创建该函数STRICT
可确保其pwd
不为空,从而节省您的另一次测试。
CREATE OR REPLACE FUNCTION registration(eml text, pwd text) RETURNS integer AS $rL$
DECLARE
emid integer;
BEGIN
INSERT INTO email (addr, passw) VALUES (eml, pwd) RETURNING id INTO emid;
RETURN emid;
EXCEPTION
WHEN unique_violation THEN
RAISE 'Email address % already registered', eml;
RETURN NULL;
END;
$rL$ LANGUAGE plpgsql STRICT;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4357 次 |
最近记录: |