【问题标题】:how to implement contains operator in Postgres如何在 Postgres 中实现包含运算符
【发布时间】:2014-07-20 15:03:56
【问题描述】:

如何实现字符串的包含运算符,如果左字符串包含在右字符串中,则返回true。

操作员名称可以是任何名称。我尝试了@@ 和下面的代码,但是

select 'A' @@ 'SAS'

返回 false。

如何解决?

CREATE OR REPLACE FUNCTION public.contains(searchFor text, searchIn text)
RETURNS bool

AS $BODY$ BEGIN

RETURN position( searchFor in searchIn)<>0;

END; $BODY$ language plpgsql immutable  RETURNS NULL ON NULL INPUT;

CREATE OPERATOR public.@@ (
    leftarg = text,
    rightarg = text,
    procedure = public.contains
);

在 windows 和 linux 中使用 Postgres 9.1 及以上版本。

select contains('A' , 'SAS' )

按预期返回真。

更新

我在答案中尝试了 9.1 代码:

CREATE OR REPLACE FUNCTION public.contains(searchFor text, searchIn text)
RETURNS bool
LANGUAGE sql IMMUTABLE
AS $BODY$
SELECT position( searchFor in searchIn )<>0;
$BODY$;


CREATE OPERATOR public.<@ (
    leftarg = text,
    rightarg = text,
    procedure = public.contains
);

但出现错误

ERROR:  column "searchin" does not exist
LINE 5: SELECT position( searchFor in searchIn )<>0;

如何使它在 9.1 中工作?在 9.3 中它可以工作。

使用

“x86_64-unknown-linux-gnu 上的 PostgreSQL 9.1.2,由 gcc-4.4.real (Debian 4.4.5-8) 4.4.5 编译,64 位”

【问题讨论】:

    标签: postgresql operators plpgsql contains


    【解决方案1】:

    PostgreSQL 已经在 pg_catalog 架构中的 (text,text) 上定义了一个 @@ 运算符,定义为:

    regress=> \do @@
                                      List of operators
       Schema   | Name | Left arg type | Right arg type | Result type |    Description    
    ------------+------+---------------+----------------+-------------+-------------------
     pg_catalog | @@   | text          | text           | boolean     | text search match
    

    这优先于您在 public 架构中定义的 @@

    我建议使用&lt;@ 运算符contains,因为that's consistent with the array contains and contained-by operatorspg_catalog text 中没有使用它...但不能保证不会在将来的版本或扩展中添加它。

    如果您想保证您的运算符优先于 pg_catalog 中的运算符,您需要将它们放在不同的模式中,并将其放在搜索路径的首位,明确在 pg_catalog 之前。所以像:

    CREATE SCHEMA my_operators;
    
    CREATE OR REPLACE FUNCTION my_operators.contains(searchFor text, searchIn text)
    RETURNS bool
    LANGUAGE sql IMMUTABLE
    AS $BODY$
    SELECT position( searchFor in searchIn)<>0;
    $BODY$;
    
    CREATE OPERATOR my_operators.<@ (
        leftarg = text,
        rightarg = text,
        procedure = public.contains
    );
    

    然后

    SET search_path = 'my_operators, pg_catalog, public';
    

    您可以使用ALTER USER 和/或ALTER DATABASE 将其设为默认值。

    【讨论】:

    • 答案不包含 RETURNS NULL ON NULL INPUT 。它应该添加到帮助计划者吗?添加COMMUTATOR, RESTRICT, JOIN, HASHES, MERGES 子句是否合理且可能?使用语言 sql 而不是 pgsql 更好吗?
    • @Andrus 实际上RETURNS NULL ON NULL INPUTSTRICT 可以禁止内联,如果可能最好省略。文档需要更清楚地说明这一点。是的,添加一个换向器@&gt; 运算符是相当合理的。我不明白你将如何实现散列。
    • 算子不存在时如何创建?我试过CREATE OPERATOR IF NOT EXISTS public.&lt;@,但出错了
    • @Andrus 使用 DO 块在 pg_operator 中查找它,我猜。不是每个语句类型都有IF NOT EXISTS。我个人强烈建议将其包装在 extension 中。该文档涵盖了扩展的创建。扩展不需要任何 C 代码,它可以只是一个 SQL 文件、Makefile 和扩展控制文件。
    • @Andrus 将 searchfor 替换为 $1,将 searcin 替换为 $2
    猜你喜欢
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    相关资源
    最近更新 更多