return 给定 table 的动态列集的函数
Function to return dynamic set of columns for given table
我有一个 fields
table 来存储其他 table 的列信息:
CREATE TABLE public.fields (
schema_name varchar(100),
table_name varchar(100),
column_text varchar(100),
column_name varchar(100),
column_type varchar(100) default 'varchar(100)',
column_visible boolean
);
我想创建一个函数来获取特定 table 的数据。
刚刚尝试过这样的事情:
create or replace function public.get_table(schema_name text,
table_name text,
active boolean default true)
returns setof record as $$
declare
entity_name text default schema_name || '.' || table_name;
r record;
begin
for r in EXECUTE 'select * from ' || entity_name loop
return next r;
end loop;
return;
end
$$
language plpgsql;
使用这个函数,我必须在调用它时指定列!
select * from public.get_table('public', 'users') as dept(id int, uname text);
我想将schema_name
和table_name
作为参数传递给函数并根据public.fields
table中的column_visible
字段获取记录列表。
我认为您只需要另一个查询来获取您想要的列列表。
可能是这样的(未经测试):
create or replace function public.get_table(_schema_name text, _table_name text, active boolean default true) returns setof record as $$
declare
entity_name text default schema_name || '.' || table_name;
r record;
columns varchar;
begin
-- Get the list of columns
SELECT string_agg(column_name, ', ')
INTO columns
FROM public.fields
WHERE fields.schema_name = _schema_name
AND fields.table_name = _table_name
AND fields.column_visible = TRUE;
-- Return rows from the specified table
RETURN QUERY EXECUTE 'select ' || columns || ' from ' || entity_name;
RETURN;
end
$$
language plpgsql;
请记住,如果 column/table 引用中包含特定字符,则可能需要用双引号括起来。
简单案例的解决方案
如以下参考答案中所述,您可以使用已注册(行)类型,从而隐式声明多态函数的 return 类型:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
致电:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Returns 完整的 table(包含所有用户列)。
等等!怎么样?
详细解释在这个相关的答案,章节
"各种完整table类型":
- Refactor a PL/pgSQL function to return the output of various SELECT queries
TABLE foo
只是 SELECT * FROM foo
:
的缩写
2 完全动态的步骤 return 类型
但是你想要做的是在单[=]中绝对不可能 126=]命令。
I want to pass schema_name
and table_name
as parameters to function and get record list, according to column_visible
field in
public.fields
table.
没有直接的方法return 从函数中任意选择列(return 类型在调用时未知) - 或 any SQL 命令。 SQL 要求在调用时知道结果列的数量、名称和类型。此相关答案的第 2 章中有更多内容:
有多种解决方法。您可以将结果包装在一种标准文档类型中(json
、jsonb
、hstore
、xml
)。
或 您使用一个函数调用生成查询并使用下一个函数调用执行结果:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
致电:
SELECT public.generate_get_table('public', 'users');
这将创建以下形式的查询:
SELECT usr_id, usr FROM public.users;
在第二步执行。 (您可能想要添加列号和排序列。)
或者在 psql 中附加 \gexec
以立即执行 return 值。参见:
一定要防御SQL注入:
- INSERT with dynamic table name in trigger function
- Define table and column names as arguments in a plpgsql function?
旁白
varchar(100)
对于标识符没有多大意义,在标准 Postgres 中标识符被限制为 63 个字符:
- Maximum characters in labels (table names, columns etc)
如果您了解对象标识符类型 regclass
的工作原理,您可以将架构和 table 名称替换为单个 regclass
列。
我有一个 fields
table 来存储其他 table 的列信息:
CREATE TABLE public.fields (
schema_name varchar(100),
table_name varchar(100),
column_text varchar(100),
column_name varchar(100),
column_type varchar(100) default 'varchar(100)',
column_visible boolean
);
我想创建一个函数来获取特定 table 的数据。 刚刚尝试过这样的事情:
create or replace function public.get_table(schema_name text,
table_name text,
active boolean default true)
returns setof record as $$
declare
entity_name text default schema_name || '.' || table_name;
r record;
begin
for r in EXECUTE 'select * from ' || entity_name loop
return next r;
end loop;
return;
end
$$
language plpgsql;
使用这个函数,我必须在调用它时指定列!
select * from public.get_table('public', 'users') as dept(id int, uname text);
我想将schema_name
和table_name
作为参数传递给函数并根据public.fields
table中的column_visible
字段获取记录列表。
我认为您只需要另一个查询来获取您想要的列列表。
可能是这样的(未经测试):
create or replace function public.get_table(_schema_name text, _table_name text, active boolean default true) returns setof record as $$
declare
entity_name text default schema_name || '.' || table_name;
r record;
columns varchar;
begin
-- Get the list of columns
SELECT string_agg(column_name, ', ')
INTO columns
FROM public.fields
WHERE fields.schema_name = _schema_name
AND fields.table_name = _table_name
AND fields.column_visible = TRUE;
-- Return rows from the specified table
RETURN QUERY EXECUTE 'select ' || columns || ' from ' || entity_name;
RETURN;
end
$$
language plpgsql;
请记住,如果 column/table 引用中包含特定字符,则可能需要用双引号括起来。
简单案例的解决方案
如以下参考答案中所述,您可以使用已注册(行)类型,从而隐式声明多态函数的 return 类型:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
致电:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Returns 完整的 table(包含所有用户列)。
等等!怎么样?
详细解释在这个相关的答案,章节 "各种完整table类型":
- Refactor a PL/pgSQL function to return the output of various SELECT queries
TABLE foo
只是 SELECT * FROM foo
:
2 完全动态的步骤 return 类型
但是你想要做的是在单[=]中绝对不可能 126=]命令。
I want to pass
schema_name
andtable_name
as parameters to function and get record list, according tocolumn_visible
field inpublic.fields
table.
没有直接的方法return 从函数中任意选择列(return 类型在调用时未知) - 或 any SQL 命令。 SQL 要求在调用时知道结果列的数量、名称和类型。此相关答案的第 2 章中有更多内容:
有多种解决方法。您可以将结果包装在一种标准文档类型中(json
、jsonb
、hstore
、xml
)。
或 您使用一个函数调用生成查询并使用下一个函数调用执行结果:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
致电:
SELECT public.generate_get_table('public', 'users');
这将创建以下形式的查询:
SELECT usr_id, usr FROM public.users;
在第二步执行。 (您可能想要添加列号和排序列。)
或者在 psql 中附加 \gexec
以立即执行 return 值。参见:
一定要防御SQL注入:
- INSERT with dynamic table name in trigger function
- Define table and column names as arguments in a plpgsql function?
varchar(100)
对于标识符没有多大意义,在标准 Postgres 中标识符被限制为 63 个字符:
- Maximum characters in labels (table names, columns etc)
如果您了解对象标识符类型 regclass
的工作原理,您可以将架构和 table 名称替换为单个 regclass
列。