使用plpgsql过程提取记录(如果存在),如果存在,则使用它做一些事情。
变量是rowtype:
my_var my_table%rowtype;
我用SQL语句填充它:
select * from my_table where owner_id = 6 into my_var;
我知道它确实有一行:
raise notice 'my_var is %', my_var;
返回:
NOTICE: my_var is (383,6,10)
但是现在我想测试一下,如果条件失败,它会记录下这些记录:
if my_var is null then
raise notice 'IT IS NULL';
end if;
if my_var is not null then
raise notice 'IT IS NOT NULL';
end if;
这些加注都没有出现在我的消息日志中 - 它只是从不进入块。如果您从SELECT * INTO
收到了一行,那么测试的正确方法是什么?
答案 0 :(得分:7)
我看到两个可能的原因,为什么......
这些加注都没有出现在我的消息日志中
首先,NOTICE
通常不会使用默认设置写入数据库日志。我引用the manual here:
log_min_messages
(enum
)控制将哪些消息级别写入服务器日志。有效值为
DEBUG5
,DEBUG4
,DEBUG3
,DEBUG2
,DEBUG1
,INFO
,NOTICE
,WARNING
,ERROR
,LOG
,FATAL
和PANIC
。 (...)
默认值为警告。请注意,LOG
的排名与client_min_messages
中的排名不同。
大胆强调我的。另请注意NOTICE
的不同默认值(client_min_messages
)(手册中的上一项)。
其次,考虑如何计算行表达式。如果(且仅当)每个元素为row_variable IS NULL
,则测试TRUE
会返回NULL
。给出以下示例:
SELECT (1, NULL) IS NULL AS a -- FALSE
,(1, NULL) IS NOT NULL AS b -- also FALSE
两个表达式都返回FALSE
。换句话说,行(或记录)变量(1, NULL)
既不是NULL
,也不是NOT NULL
。因此,两个测试都失败了。
- > SQLfiddle with more details.
此相关答案中CHECK
约束中此行为的更多详细信息,说明,链接和可能的应用:
NOT NULL constraint over a set of columns
您甚至可以使用NULL(rec := NULL
)分配记录变量,这会导致每个元素都为NULL - 如果类型是众所周知的行类型。否则,我们正在处理匿名记录,结构未定义,您无法访问元素。但是,在您的示例中,rowtype
之类的情况并非如此(这一直是众所周知的)。
FOUND
如果您从
SELECT * INTO
收到了一行,那么测试的正确方法是什么?
您必须考虑该行可能为NULL,即使已分配。查询很可能返回了一堆NULL值(如果查询中的表定义允许NULL值)。这样的测试在设计上是不可靠的。
有一种简单而安全的方法。使用GET DIAGNOSTICS ...
或(如果适用)特殊变量FOUND
:
SELECT * FROM my_table WHERE owner_id = 6 INTO my_var;
IF NOT FOUND THEN
RAISE NOTICE 'Query did not return a row!';
END IF;