我是PG/GP的纽比。我需要write函数返回完整的Greenplum表定义(如dbeaver DDL选项卡)。在我的系统函数get_table_def
中,catalog.pg_gettabledef
不存在,或对我不可用。我不知道为什么,也许是用户权限不够。
我已经找到了一个函数,它返回setof text
和表结构定义:
CREATE OR REPLACE FUNCTION describe_table(p_schema_name varchar, p_table_name varchar)
RETURNS SETOF text
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
v_table_ddl text;
column_record record;
table_rec record;
constraint_rec record;
firstrec boolean;
BEGIN
FOR table_rec IN
SELECT c.relname, c.oid FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE relkind = 'r'
AND n.nspname = p_schema_name
AND relname~ ('^('||p_table_name||')$')
ORDER BY c.relname
LOOP
FOR column_record IN
SELECT
b.nspname as schema_name,
b.relname as table_name,
a.attname as column_name,
pg_catalog.format_type(a.atttypid, a.atttypmod) as column_type,
CASE WHEN
(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
FROM pg_catalog.pg_attrdef d
WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) IS NOT NULL THEN
'DEFAULT '|| (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
FROM pg_catalog.pg_attrdef d
WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)
ELSE
''
END as column_default_value,
CASE WHEN a.attnotnull = true THEN
'NOT NULL'
ELSE
'NULL'
END as column_not_null,
a.attnum as attnum,
e.max_attnum as max_attnum
FROM
pg_catalog.pg_attribute a
INNER JOIN
(SELECT c.oid,
n.nspname,
c.relname
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.oid = table_rec.oid
ORDER BY 2, 3) b
ON a.attrelid = b.oid
INNER JOIN
(SELECT
a.attrelid,
max(a.attnum) as max_attnum
FROM pg_catalog.pg_attribute a
WHERE a.attnum > 0
AND NOT a.attisdropped
GROUP BY a.attrelid) e
ON a.attrelid=e.attrelid
WHERE a.attnum > 0
AND NOT a.attisdropped
ORDER BY a.attnum
LOOP
IF column_record.attnum = 1 THEN
v_table_ddl:='CREATE TABLE '||column_record.schema_name||'.'||column_record.table_name||' (';
ELSE
v_table_ddl:=v_table_ddl||',';
END IF;
IF column_record.attnum <= column_record.max_attnum THEN
v_table_ddl:=v_table_ddl||chr(10)||
' '||column_record.column_name||' '||column_record.column_type||' '||column_record.column_default_value||' '||column_record.column_not_null;
END IF;
END LOOP;
firstrec := TRUE;
FOR constraint_rec IN
SELECT conname, pg_get_constraintdef(c.oid) as constrainddef
FROM pg_constraint c
WHERE conrelid=(
SELECT attrelid FROM pg_attribute
WHERE attrelid = (
SELECT oid FROM pg_class WHERE relname = table_rec.relname
AND relnamespace = (SELECT ns.oid FROM pg_namespace ns WHERE ns.nspname = p_schema_name)
) AND attname='tableoid'
)
LOOP
v_table_ddl:=v_table_ddl||','||chr(10);
v_table_ddl:=v_table_ddl||'CONSTRAINT '||constraint_rec.conname;
v_table_ddl:=v_table_ddl||chr(10)||' '||constraint_rec.constrainddef;
firstrec := FALSE;
END LOOP;
v_table_ddl:=v_table_ddl||');';
RETURN NEXT v_table_ddl;
END LOOP;
END;
$$
EXECUTE ON ANY;
字符串
现在我想编写另一个类似的函数,它基于select返回setof text
,其中包含3行数据集(Greenplum表的其他部分DDL,其中包含分区信息):
CREATE OR REPLACE FUNCTION kasudra_dds.describe_table1(p_schema_name varchar, p_table_name varchar)
RETURNS SETOF text
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
v_table_ddl text;
column_record record;
table_rec record;
constraint_rec record;
firstrec boolean;
BEGIN
FOR table_rec IN
select
n.nspname as schemaname,
c.relname as tablename,
a.attname as columnname,
p.parlevel as partitionlevel,
p.i + 1 as position_in_partition_key
from
pg_namespace n,
pg_class c,
pg_attribute a,
(
select
p.parrelid,
p.parlevel,
p.paratts[i.i] as attnum,
i.i
from
pg_partition p,
generate_series(0,
(
select
max(array_upper(pg_partition.paratts, 1)) as max
from
pg_partition)) i(i)
where
p.paratts[i.i] is not null) p
where
p.parrelid = c.oid and
c.relnamespace = n.oid and
p.attnum = a.attnum and
a.attrelid = c.oid and
n.nspname = $1 and
c.relname = $2
order by
p.parlevel
LOOP
v_table_ddl:=v_table_ddl||'PARTITION BY LIST ('||table_rec.columnname||')'||chr(10);
RETURN NEXT v_table_ddl;
END LOOP;
END;
$$
EXECUTE ON ANY;
1条答案
按热度按时间83qze16e1#
您得到
null
是因为您没有初始化变量v_table_ddl
,因此它默认为null
。null || anything
是null
。字符串
在
DECLARE
部分将解决这个问题。但整个功能似乎非常复杂。我怀疑你想从一开始就返回
setof text
。看起来你只想返回一个连接的text
值。而且你很可能也不需要循环。模板函数看起来也不是很成熟。首先,它在没有正确的双引号的情况下连接标识符,这会导致语法错误和需要双引号的名称的SQL注入。请参阅:
至少内部循环可以用普通SQL中的聚合来代替。
要在Postgres中获得重新设计的
CREATE TABLE
脚本,请使用pgAdmin(或任何GUI),或从shell中使用pg_dump
:型
相关内容:
最后,记住用
SELECT * FROM ...
调用返回集合的函数。请参阅: