使用 EXECUTE 时的 Postgres 10 和格式错误的数组文字
Postgres 10 and malformatted array literal when using EXECUTE
我正在尝试在 Postgres 10 上创建一个函数来检查是否所有给定的 ID 都存在
在目标 table.
CREATE OR REPLACE FUNCTION "public"."has_mismatching_ids"(
_ids TEXT[],
_column_name TEXT,
_table_name TEXT,
_schema_name TEXT DEFAULT 'public'
)
RETURNS BOOLEAN AS
$$
DECLARE
result TEXT[] := '{}';
_query TEXT := '';
BEGIN
IF _ids IS NULL THEN
RETURN false;
END IF;
_query := CONCAT('SELECT UNNEST() EXCEPT SELECT "', _column_name, '" FROM "', _schema_name ,'"."', _table_name ,'"');
EXECUTE _query INTO result USING ;
RAISE NOTICE 'Executed';
IF array_length(result, 1) > 0 THEN
RETURN true;
END IF;
RETURN false;
END;
$$
LANGUAGE plpgsql
STABLE
SECURITY INVOKER;
这是我的函数,如果所有 ID 都存在,returns 正确为真,但如果有任何一个,它会抛出异常
ID 不存在。
CREATE TABLE "public"."categories" ("category_id" TEXT NOT NULL PRIMARY KEY);
INSERT INTO "public"."categories" ("category_id") VALUES ('foo');
INSERT INTO "public"."categories" ("category_id") VALUES ('bar');
这个有效
SELECT FROM "public"."has_mismatching_ids"(ARRAY['foo'], 'category_id', 'categories', 'public');
NOTICE: Executed
has_mismatching_ids
---------------------
f
(1 row)
但这甚至都失败了
SELECT FROM "public"."has_mismatching_ids"(ARRAY['foo2'], 'category_id', 'categories', 'public');
ERROR: malformed array literal: "foo2"
DETAIL: Array value must start with "{" or dimension information.
CONTEXT: PL/pgSQL function public.has_mismatching_ids(text[],text,text,text) line 14 at EXECUTE
奇怪的是,如果我编写一个使用显式名称且没有 EXECUTE
的函数,这也有效
SELECT UNNEST(ARRAY['foo', 'foo3']) EXCEPT SELECT "category_id" FROM "public"."categories";
unnest
--------
foo3
(1 row)
为什么我的动态函数在与目标 table 中不存在的值进行比较时不起作用?
您可以使用简单的SQL来比较是否所有数组元素都存在。
CREATE OR replace FUNCTION "public"."has_mismatching_ids"(
_ids text[],
_column_name text,
_table_name text,
_schema_name text DEFAULT 'public' )
returns boolean AS $$
DECLARE res BOOLEAN;
BEGIN
IF _ids IS NULL then
RETURN false;
END IF;
EXECUTE format ( 'SELECT COUNT(*) = cardinality()
FROM %I.%I WHERE %I = ANY()',
_schema_name,_table_name,_column_name )
INTO res using _ids, _ids;
RETURN res;
END;
$$ language plpgsql stable security invoker;
我正在尝试在 Postgres 10 上创建一个函数来检查是否所有给定的 ID 都存在 在目标 table.
CREATE OR REPLACE FUNCTION "public"."has_mismatching_ids"(
_ids TEXT[],
_column_name TEXT,
_table_name TEXT,
_schema_name TEXT DEFAULT 'public'
)
RETURNS BOOLEAN AS
$$
DECLARE
result TEXT[] := '{}';
_query TEXT := '';
BEGIN
IF _ids IS NULL THEN
RETURN false;
END IF;
_query := CONCAT('SELECT UNNEST() EXCEPT SELECT "', _column_name, '" FROM "', _schema_name ,'"."', _table_name ,'"');
EXECUTE _query INTO result USING ;
RAISE NOTICE 'Executed';
IF array_length(result, 1) > 0 THEN
RETURN true;
END IF;
RETURN false;
END;
$$
LANGUAGE plpgsql
STABLE
SECURITY INVOKER;
这是我的函数,如果所有 ID 都存在,returns 正确为真,但如果有任何一个,它会抛出异常 ID 不存在。
CREATE TABLE "public"."categories" ("category_id" TEXT NOT NULL PRIMARY KEY);
INSERT INTO "public"."categories" ("category_id") VALUES ('foo');
INSERT INTO "public"."categories" ("category_id") VALUES ('bar');
这个有效
SELECT FROM "public"."has_mismatching_ids"(ARRAY['foo'], 'category_id', 'categories', 'public');
NOTICE: Executed
has_mismatching_ids
---------------------
f
(1 row)
但这甚至都失败了
SELECT FROM "public"."has_mismatching_ids"(ARRAY['foo2'], 'category_id', 'categories', 'public');
ERROR: malformed array literal: "foo2"
DETAIL: Array value must start with "{" or dimension information.
CONTEXT: PL/pgSQL function public.has_mismatching_ids(text[],text,text,text) line 14 at EXECUTE
奇怪的是,如果我编写一个使用显式名称且没有 EXECUTE
SELECT UNNEST(ARRAY['foo', 'foo3']) EXCEPT SELECT "category_id" FROM "public"."categories";
unnest
--------
foo3
(1 row)
为什么我的动态函数在与目标 table 中不存在的值进行比较时不起作用?
您可以使用简单的SQL来比较是否所有数组元素都存在。
CREATE OR replace FUNCTION "public"."has_mismatching_ids"(
_ids text[],
_column_name text,
_table_name text,
_schema_name text DEFAULT 'public' )
returns boolean AS $$
DECLARE res BOOLEAN;
BEGIN
IF _ids IS NULL then
RETURN false;
END IF;
EXECUTE format ( 'SELECT COUNT(*) = cardinality()
FROM %I.%I WHERE %I = ANY()',
_schema_name,_table_name,_column_name )
INTO res using _ids, _ids;
RETURN res;
END;
$$ language plpgsql stable security invoker;