COALESCE 似乎不会在 Postgres 12 SQL 存储函数中触发
COALESCE doesn't seem to fire in Postgres 12 SQL stored function
使用 Postgres 12.x,我刚刚 运行 遇到了一个奇怪的问题。出于某种原因,我没有让 COALESCE
在存储的 SQL 函数中工作。意思是,我得到 NULL
而不是我的第一个非空值。
我怀疑我错过了一些明显的东西,但看不到它。任何人都可以发现问题所在吗?我构建了一个重现该问题的独立示例。
谢谢
测试设置
BEGIN;
------------------------------------
-- Define table
------------------------------------
DROP TABLE IF EXISTS lookup_table CASCADE;
CREATE TABLE IF NOT EXISTS lookup_table (
id uuid NOT NULL DEFAULT NULL, -- Values are geneated by an outside system.
name_ citext NOT NULL DEFAULT NULL
);
------------------------------------
-- Seed
------------------------------------
INSERT INTO lookup_table (id, name_)
VALUES ('6ea225f3-9819-49eb-bdb8-f3ae23af6337', 'John'),
('ae2282c6-ca9b-413f-b182-a1ca69fc3c78', 'Alice'),
('7ee1ce1b-4efc-426c-a6f8-5b2375cb357e', 'Magrite'),
('71c3d96a-3ac7-454e-bfff-e5551428c017', 'Arjun');
------------------------------------
-- Define the lookup fnction
------------------------------------
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
-- For some reason, COALESCE doesn't work here, but does outside of a function. Weird.
-- Tried with CTE, same same.
SELECT COALESCE (name_ , '') FROM lookup_table WHERE id = id_in;
$BODY$
LANGUAGE SQL;
------------------------------------
-- Test it out
------------------------------------
SELECT 'Alice' AS description,
lookup_function ('ae2282c6-ca9b-413f-b182-a1ca69fc3c78') AS result
UNION ALL
SELECT 'Should return an empty string, returns NULL instead' AS description,
lookup_function ('00000000-0000-0000-0000-000000000000') AS result
标准调用
为了进行比较,下面是 SELECT
中的标准调用,效果很好:
select coalesce (name_, '')
from lookup_table
where id = '00000000-0000-0000-0000-000000000000';
-- Returns an empty string, not NULL.
但是,在 SQL 函数中,此表达式 returns NULL
代替。
CTE 尝试
这是我尝试使用 CTE 来帮助实现该功能,但我还是回来了 NULL
。
------------------------------------
-- Define the lookup fnction
------------------------------------
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
WITH lookup_result AS (
select name_ from lookup_table where id = id_in
)
SELECT CASE WHEN name_ IS NULL THEN ''
ELSE name_ END
FROM lookup_result
$BODY$
LANGUAGE SQL;
查找函数不会 return 来自其中 select 语句的任何内容,因为 where 子句失败。因此永远不会执行合并。
默认情况下 return 为 null。
您可以将 select 重写为:
select coalesce((SELECT name_ FROM lookup_table WHERE id = id_in),'');
合并会将 name_ 的 NULL 值变成空字符串。但是您没有该列的 NULL 值,您有零行。这会在稍后阶段转换为 NULL,此时合并无法处理它。
也许你想要这个:
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
SELECT COALESCE (name_ , '') FROM (values (id_in))f(x) left join lookup_table on id = x;
$BODY$
LANGUAGE SQL;
使用 Postgres 12.x,我刚刚 运行 遇到了一个奇怪的问题。出于某种原因,我没有让 COALESCE
在存储的 SQL 函数中工作。意思是,我得到 NULL
而不是我的第一个非空值。
我怀疑我错过了一些明显的东西,但看不到它。任何人都可以发现问题所在吗?我构建了一个重现该问题的独立示例。
谢谢
测试设置
BEGIN;
------------------------------------
-- Define table
------------------------------------
DROP TABLE IF EXISTS lookup_table CASCADE;
CREATE TABLE IF NOT EXISTS lookup_table (
id uuid NOT NULL DEFAULT NULL, -- Values are geneated by an outside system.
name_ citext NOT NULL DEFAULT NULL
);
------------------------------------
-- Seed
------------------------------------
INSERT INTO lookup_table (id, name_)
VALUES ('6ea225f3-9819-49eb-bdb8-f3ae23af6337', 'John'),
('ae2282c6-ca9b-413f-b182-a1ca69fc3c78', 'Alice'),
('7ee1ce1b-4efc-426c-a6f8-5b2375cb357e', 'Magrite'),
('71c3d96a-3ac7-454e-bfff-e5551428c017', 'Arjun');
------------------------------------
-- Define the lookup fnction
------------------------------------
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
-- For some reason, COALESCE doesn't work here, but does outside of a function. Weird.
-- Tried with CTE, same same.
SELECT COALESCE (name_ , '') FROM lookup_table WHERE id = id_in;
$BODY$
LANGUAGE SQL;
------------------------------------
-- Test it out
------------------------------------
SELECT 'Alice' AS description,
lookup_function ('ae2282c6-ca9b-413f-b182-a1ca69fc3c78') AS result
UNION ALL
SELECT 'Should return an empty string, returns NULL instead' AS description,
lookup_function ('00000000-0000-0000-0000-000000000000') AS result
标准调用
为了进行比较,下面是 SELECT
中的标准调用,效果很好:
select coalesce (name_, '')
from lookup_table
where id = '00000000-0000-0000-0000-000000000000';
-- Returns an empty string, not NULL.
但是,在 SQL 函数中,此表达式 returns NULL
代替。
CTE 尝试
这是我尝试使用 CTE 来帮助实现该功能,但我还是回来了 NULL
。
------------------------------------
-- Define the lookup fnction
------------------------------------
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
WITH lookup_result AS (
select name_ from lookup_table where id = id_in
)
SELECT CASE WHEN name_ IS NULL THEN ''
ELSE name_ END
FROM lookup_result
$BODY$
LANGUAGE SQL;
查找函数不会 return 来自其中 select 语句的任何内容,因为 where 子句失败。因此永远不会执行合并。 默认情况下 return 为 null。
您可以将 select 重写为:
select coalesce((SELECT name_ FROM lookup_table WHERE id = id_in),'');
合并会将 name_ 的 NULL 值变成空字符串。但是您没有该列的 NULL 值,您有零行。这会在稍后阶段转换为 NULL,此时合并无法处理它。
也许你想要这个:
CREATE OR REPLACE FUNCTION lookup_function (id_in uuid)
RETURNS citext AS
$BODY$
SELECT COALESCE (name_ , '') FROM (values (id_in))f(x) left join lookup_table on id = x;
$BODY$
LANGUAGE SQL;