【问题标题】:COALESCE doesn't seem to fire in Postgres 12 SQL stored function在 Postgres 12 SQL 存储函数中似乎没有触发 COALESCE
【发布时间】:2021-01-30 22:11:35
【问题描述】:

使用 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 函数中,此表达式改为返回 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;

【问题讨论】:

  • 我没有看到那个工作时间:select coalesce(name_, 'test') from lookup_table where id = '00000000-0000-0000-0000-000000000000'; coalesce ---------- (0 rows) 你需要显示CTE 确实有效。我猜有一个JOIN 提供了一个价值。
  • 感谢您的评论,我更新了示例以显示表达式在直 SELECT 中按预期工作。 CTE(或子查询)对函数的行为没有任何影响,因此我将示例保留为最简单的形式。而且,在这种情况下,没有 JOIN,它真的是直接查找。
  • 不,它没有。添加pg_typeof(coalesce (name_, '')),您将不会返回任何内容。

标签: postgresql plpgsql coalesce


【解决方案1】:

查找函数不会从其中的 select 语句返回任何内容,因为 where 子句失败。因此,永远不会执行合并。 默认返回null。

您可以将选择重写为:
select coalesce((SELECT name_ FROM lookup_table WHERE id = id_in),'');

【讨论】:

    【解决方案2】:

    合并会将 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;
    

    【讨论】:

    • 谢谢,这也很好用!我将使用上一个答案,就像我发现代码更易于遵循一样。
    猜你喜欢
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    相关资源
    最近更新 更多