【问题标题】:Text equality (including null values) in Postgres plpgsql stored functionPostgres plpgsql 存储函数中的文本相等(包括空值)
【发布时间】:2012-06-21 04:23:36
【问题描述】:

我有一个存储函数,它应该比较三个文本值是否相等。其中一些文本值可能为 null,如果为 null,则比较应返回 false 值。

CREATE OR REPLACE FUNCTION "subject_check_if_subjectName_exists"(name1IN text, name2IN text, name3IN text, name4IN text)
returns boolean as
$$
declare
    results boolean;
    subjectList record;
begin
    results = false;
    for subjectList in select name1, name2, name3, name4 from subject loop
    if (name1In = subjectList.name1) and (name2In = subjectList.name2) and (name3In = subjectList.name3) and (name4In = subjectList.name4)
      then
        results = true;
        EXIT; -- exit out of loop
    end if;
    end loop;
    return results;
end;
$$ language 'plpgsql';

name4IN 和 subjectList.name4 都为 null,并且所有其他值都相等,该函数不返回真值 - 它应该返回。我如何比较这些文本值,即使它们为 null(null = null 应该返回 true)?

【问题讨论】:

    标签: sql postgresql null equals plpgsql


    【解决方案1】:

    使用合并:

    if (coalesce(name1In, '') = coalesce(subjectList.name1, '') ....
    

    【讨论】:

    • 我一定是做错了什么。我已经读过,coalesce 返回列表中的第一个非空值...并且在使用此修改后的 if 语句运行相同的存储过程时出现此错误:if (coalesce(name1IN, '') = coalesce(subjectList.name1), '') then results = true; exit; end if; 这是错误:********** Error ********** ERROR: invalid input syntax for type boolean: "(f,"")" SQL state: 22P02 Context: PL/pgSQL function "subject_check_if_subjectName_exists" line 7 at IF跨度>
    【解决方案2】:

    我想你想用is not distinct from:

    对于非空输入,IS DISTINCT FROM<> 运算符相同。但是,如果两个输入都为 null,则返回 false,如果只有一个输入为 null,则返回 true。同样,IS NOT DISTINCT FROM= 对于非空输入相同,但当两个输入都为空时返回 true,当只有一个输入为空时返回 false。

    本质上,A is not distinct from B 类似于A = B,但它将 NULL 视为“相等”(即它的行为就像大多数 SQL 新手认为 = 应该的那样)。例如,考虑这样一个简单的函数:

    create function f(text,text) returns text as $$
    begin
        if $1 is distinct from $2 then
            return '!=';
        end if;
        return '==';
    end $$
    language plpgsql;
    

    这会给你这样的结果:

    => select f(null, null) as "1"
              f(null, '') as "2",
              f('', '') as "3",
              f('pancakes','pancakes') as "4",
              f('pancakes', null) as "5",
              f('pancakes', 'house') as "6";
     1  | 2  | 3  | 4  | 5  | 6  
    ----+----+----+----+----+----
     == | != | == | == | != | !=
    

    所以你正在寻找这样的东西:

    if (name1In is not distinct from subjectList.name1) and ...
    

    【讨论】:

    • 没错。感谢您正确提出我的问题。不太好解释自己。我会尽快试试这个。我已经写出了适用于多个 if 语句的函数……但 IS NOT DISTINCT FROM 似乎是一种更快的方法。请看下一个答案。
    • @user1295681:而且比试图确保用一堆巢ifs 覆盖所有情况要容易得多。
    【解决方案3】:

    基本上,这就是我想要做的。我认为必须有一种更快的方法来比较包括空值在内的值。这就是我想要它做的事情:

    -- Function to check subject names (name1,2,3 and 4) already exists
    CREATE OR REPLACE FUNCTION "subject_check_if_subjectName_exists"(name1IN text, name2IN text, name3IN text, name4IN text)
    returns boolean as
    $$
    declare
        results boolean;
        subjectList record;
    begin
        results = false;
        for subjectList in select name1, name2, name3, name4 from subject loop
        if ((subjectList.name4 is null) and (name4IN is null)) then
            if ((subjectList.name3 is null) and (name3IN is null)) then
            if ((subjectList.name2 is null) and (name2IN is null)) then
              if (name1IN = subjectList.name1) then
                results = true;
                EXIT;
              end if;
            else
              if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2)) then
                results = true;
                EXIT;
              end if;
            end if;
            else
              if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2) and (name3IN = subjectList.name3)) then
            results = true;
            EXIT;
              end if;
            end if;
        else
          if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2) and (name3IN = subjectList.name3) and (name4IN = subjectList.name4)) then
            results = true;
            EXIT;
              end if;
        end if;
        end loop;
        return results;
    end;
    $$ language 'plpgsql';
    

    将尝试与现在不同。

    感谢您的帮助。非常感谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 2015-01-05
      • 2019-03-26
      • 2021-04-16
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多