web-dev-qa-db-ja.com

エラー:演算子が存在しません:text [] ~~ text

単一のスカラーの配列を調べることができる簡単な構文があります。

SELECT 'foo' = ANY(ARRAY['foo', 'bar', 'baz']);

同じ方法を使用してLIKEと照合できます

SELECT 'foobar' LIKE ANY(ARRAY['foo%', 'bar%', 'baz%'];

私の質問は、あなたが他のことをしたい場合はどうでしょうか。

SELECT ANY(ARRAY['foobar', 'barbar', 'bazbar']) LIKE 'foo%' 
ERROR:  syntax error at or near "ANY"
LINE 1: SELECT ANY(ARRAY['foobar', 'barbar', 'bazbar']) LIKE 'foo%';

構文が機能しないことは知っていますが、これが機能することを期待しています。

# SELECT ARRAY['foobar', 'barbar', 'bazbar'] LIKE 'foo%';
ERROR:  operator does not exist: text[] ~~ unknown
LINE 1: SELECT ARRAY['foobar', 'barbar', 'bazbar'] LIKE 'foo%';
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

配列をフィルタリングして、要素が存在するかどうかを確認したいと思います。これはunnestを使用せずに可能ですか?

3
Evan Carroll

Postgresマニュアル suggests 設計上の問題があるかもしれません:

配列はセットではありません。特定の配列要素を検索することは、データベースの設計ミスの兆候である可能性があります。配列要素となる項目ごとに行を持つ個別のテーブルを使用することを検討してください。これは検索が容易になり、多数の要素に対してより適切にスケーリングされる可能性があります。

your operator をより効率的にすることができます—最初の一致後にチェックを停止する方が良いです:

CREATE OR REPLACE FUNCTION like_in_array( arr text[], pattern text )
RETURNS bool AS $$
  SELECT coalesce(( SELECT true
                    FROM unnest(arr) AS u(n)
                    WHERE n LIKE pattern 
                    LIMIT 1),false);
$$ LANGUAGE sql
IMMUTABLE;

dbfiddle ここ

Evanの演算子解 の関数がよりシンプルになり、さらに高速になるはずです。

CREATE OR REPLACE FUNCTION like_in_array(_arr text[], _pattern text)
  RETURNS bool LANGUAGE sql IMMUTABLE AS
'SELECT EXISTS (SELECT 1 FROM unnest($1) n WHERE n ~~ $2)';

迅速かつ汚い選択肢

配列をtextにキャストするだけです:

全文一致:

SELECT (ARRAY['foobar', 'barbar', 'bazbar'])::text LIKE '%foo%';

パターンと文字列には、デコレータ文字(,"{})正解です。

プレフィックスの一致:

SELECT (ARRAY['foo bar', 'barbar', 'bazbar'])::text ~ '[{",]foo';

文字列のパターンまたはにデコレータ文字がありません。
等。

これは、たとえばトライグラムインデックスを使用してインデックスを付けることができるため、カスタムオペレーターよりもmuch高速になる可能性があります。

dbfiddle ここ(ジャックのフィドルに基づく)

3

parray_gin 拡張( またはそれ以上 )を確認することをお勧めします。それはあなたのためにいくつかの新しい演算子を作成しますが(注意しないとそれらのいくつかは同じ名前の組み込み演算子と干渉する可能性があります)、それはインデックス付けもサポートします。

2
jjanes

独自のオペレーターを作る

CREATE OPERATOR 。これが最善の方法かどうかはわかりません。午前2時です...

CREATE OR REPLACE FUNCTION like_in_array( arr text[], pattern text )
RETURNS bool AS $$
  SELECT n LIKE pattern
  FROM unnest(arr) AS u(n)
  ORDER BY 1 DESC
  LIMIT 1;
$$ LANGUAGE sql
IMMUTABLE;

CREATE OPERATOR ~~ (
  LEFTARG   = TEXT[],
  RIGHTARG  = TEXT,
  PROCEDURE = like_in_array
);

テスト、

SELECT ARRAY['foobar', 'barbar', 'bazbar'] LIKE 'foo%';
 ?column? 
----------
 t
(1 row)
0
Evan Carroll