如果我有桌子
create table foo ( bar text[] not null check ..... );
和一个功能
create function baz(text) returns boolean as $$ .....
如何在foo表中添加检查约束,以便bar字段中的每个元素都验证baz函数?
我在想我需要创建一个函数
create function array_baz(arg text[]) returns boolean as $$
with x as ( select baz(unnest(arg)) as s_arg )
select not exists (select 1 from x where s_arg = false)
$$ language sql strict immutable;
create table foo (bar text[] not null check ( array_baz(bar) = true ) );
然而,我确信我在这里重新发明轮子,这是一种可行的方法。我错过了什么psql技巧?地图功能很不错
create table foo (bar text[] not null check (true = all(map('baz', bar)));
但到目前为止,我的搜索工作毫无结果。
答案 0 :(得分:2)
你可以通过多种方式做你想做的事。如果要使用ALL(...)
量词,则需要合适的运算符。为此,您首先需要一个功能来执行您想要的任务:
想象一下,您想要检查您的文本中是否包含任何大写字母。你定义了一个像:
这样的函数CREATE FUNCTION doesnt_have_uppercase(b boolean, t text)
/* Compares b to the result of `t` not having any non-lowercase character */
RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT (t = lower(t)) = b
$$ ;
基于此,create an operator:
CREATE OPERATOR =%= (
PROCEDURE = doesnt_have_uppercase,
LEFTARG = boolean,
RIGHTARG = text
) ;
您需要此运算符,因为ANY
and ALL
quantifiers需要以下结构:
expression operator ALL(array)
此时,您可以定义:
create table foo
(
bar text[] not null,
CONSTRAINT bar_texts_cant_have_uppercase CHECK(true =%= ALL(bar))
);
这将引导您出现以下行为:
INSERT INTO foo
(bar)
VALUES
(ARRAY['this will pass', 'this too']) ;
1 rows affected
INSERT INTO foo
(bar)
VALUES
(ARRAY['that would pass', 'BUT THIS WILL PREVENT IT']) ;
ERROR: new row for relation "foo" violates check constraint "bar_texts_cant_have_uppercase" DETAIL: Failing row contains ({"that would pass","BUT THIS WILL PREVENT IT"}).
全部检查 dbfiddle here
但是,我很可能会寻求一条不那么曲折的路线:CREATE FUNCTION doesnt_have_uppercase(t text[])
/* Returns true if all elements of t don't have any uppercase letter */
RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT (NOT EXISTS (SELECT 1 FROM unnest(t) q WHERE q <> lower(q)))
$$ ;
create table foo
(
bar text[] not null,
CONSTRAINT bar_texts_cant_have_uppercase CHECK(doesnt_have_uppercase(bar))
);
这与上一个示例完全相同(除非数组的某些元素为NULL)。
dbfiddle here