Select 列如果存在否则为空 - PSQL
Select column if exists else null - PSQL
以下函数动态连接不同的表。
create or replace function unified_tables() returns table(
1 TEXT
, 2 TEXT
, 3 TEXT
, 4 TEXT
, 5 JSONB
, 6 BIGINT
, 7 BIGINT
, 8 TEXT
, 9 TEXT
, 10 TIMESTAMPTZ
)
as
$$
declare
a record;
begin
for a in select table_schema
from information_schema.tables
where table_name = 'name'
loop
return query
execute format('select %L as source_schema, * from %I.name', a.table_schema, a.table_schema);
end loop;
end;
$$
language plpgsql;
不幸的是,并非所有调用的表都具有 RETURNS TABLE 中指定的所有列。
准确地说,有 15 个表(循环超过 200 个表)缺少第 2 列,两个表缺少第 4 列,五个表缺少第 9 列。
进入循环的未来表也可能会丢失列。我无法控制源结构。
如何继续使用为缺失列添加空值的函数,以维护 RETURNS TABLE 中定义的结构?
您将无法编写能够满足您需求的查询。您将需要构建代码。最简单的方法是将目标 table 的 information_schema.columns 与所需列名列表一起使用。这本身就产生了一个问题,因为“未来 tables 进入循环也可能会丢失列”,并且您可能事先不知道这些列是什么,以及必要列更改时的维护问题。现在这并不意味着没有简单的答案。只是不是您要查询的内容。
最简单的方法是使用所需的列名和数据类型创建一个模板 table。然后是一个将模板列与目标 table 列连接起来的函数。对于列维护,您只需更改模板 table。 (参见 Demo here)
create table unified_def
(c1 text
,c2 text
,c3 text
,c4 text
,c5 jsonb
,c6 bigint
,c7 bigint
,c8 text
,c9 text
,c10 timestamptz
);
create or replace
function unified_tables(target_table_in text)
returns setof unified_def
language plpgsql
as $$
declare
def_cur cursor( c_tgt_table text ) for
with ud(column_name,data_type, ordinal_position) as
( select column_name,data_type,ordinal_position
from information_schema.columns
where table_name = 'unified_def'
order by ordinal_position
) --select * from ud
, tgt (column_name) as
( select column_name
from information_schema.columns
where table_name = c_tgt_table
) --select * from tgt
select ud.column_name cname
, tgt.column_name tname
, ud.data_type
from ud left join tgt on (ud.column_name = tgt.column_name);
l_from text = ' from <tbl>';
l_sep text = '';
l_stmt text = 'select ';
begin
for cdef in def_cur(target_table_in)
loop
l_stmt = l_stmt || l_sep
|| coalesce(cdef.tname, 'null::' || cdef.data_type);
l_sep = ',';
end loop;
l_stmt = l_stmt || replace (l_from, '<tbl>', target_table_in);
raise notice E'Run Statement \n%', l_stmt;
return query execute l_stmt;
end;
$$;
注意: 上述函数假定模板和目标 table 之间的数据类型兼容。如果存在这种情况不成立的情况,则需要额外的代码来处理这种情况。在任何情况下,最终的 return 类型 必须 符合模板的定义 table.
以下函数动态连接不同的表。
create or replace function unified_tables() returns table(
1 TEXT
, 2 TEXT
, 3 TEXT
, 4 TEXT
, 5 JSONB
, 6 BIGINT
, 7 BIGINT
, 8 TEXT
, 9 TEXT
, 10 TIMESTAMPTZ
)
as
$$
declare
a record;
begin
for a in select table_schema
from information_schema.tables
where table_name = 'name'
loop
return query
execute format('select %L as source_schema, * from %I.name', a.table_schema, a.table_schema);
end loop;
end;
$$
language plpgsql;
不幸的是,并非所有调用的表都具有 RETURNS TABLE 中指定的所有列。
准确地说,有 15 个表(循环超过 200 个表)缺少第 2 列,两个表缺少第 4 列,五个表缺少第 9 列。
进入循环的未来表也可能会丢失列。我无法控制源结构。
如何继续使用为缺失列添加空值的函数,以维护 RETURNS TABLE 中定义的结构?
您将无法编写能够满足您需求的查询。您将需要构建代码。最简单的方法是将目标 table 的 information_schema.columns 与所需列名列表一起使用。这本身就产生了一个问题,因为“未来 tables 进入循环也可能会丢失列”,并且您可能事先不知道这些列是什么,以及必要列更改时的维护问题。现在这并不意味着没有简单的答案。只是不是您要查询的内容。
最简单的方法是使用所需的列名和数据类型创建一个模板 table。然后是一个将模板列与目标 table 列连接起来的函数。对于列维护,您只需更改模板 table。 (参见 Demo here)
create table unified_def
(c1 text
,c2 text
,c3 text
,c4 text
,c5 jsonb
,c6 bigint
,c7 bigint
,c8 text
,c9 text
,c10 timestamptz
);
create or replace
function unified_tables(target_table_in text)
returns setof unified_def
language plpgsql
as $$
declare
def_cur cursor( c_tgt_table text ) for
with ud(column_name,data_type, ordinal_position) as
( select column_name,data_type,ordinal_position
from information_schema.columns
where table_name = 'unified_def'
order by ordinal_position
) --select * from ud
, tgt (column_name) as
( select column_name
from information_schema.columns
where table_name = c_tgt_table
) --select * from tgt
select ud.column_name cname
, tgt.column_name tname
, ud.data_type
from ud left join tgt on (ud.column_name = tgt.column_name);
l_from text = ' from <tbl>';
l_sep text = '';
l_stmt text = 'select ';
begin
for cdef in def_cur(target_table_in)
loop
l_stmt = l_stmt || l_sep
|| coalesce(cdef.tname, 'null::' || cdef.data_type);
l_sep = ',';
end loop;
l_stmt = l_stmt || replace (l_from, '<tbl>', target_table_in);
raise notice E'Run Statement \n%', l_stmt;
return query execute l_stmt;
end;
$$;
注意: 上述函数假定模板和目标 table 之间的数据类型兼容。如果存在这种情况不成立的情况,则需要额外的代码来处理这种情况。在任何情况下,最终的 return 类型 必须 符合模板的定义 table.