Postgresql 计算所有表中所有架构(授予权限)中的行数

Postgresql 计算所有表中所有架构(授予权限)中的行数,postgresql,count,schema,database-table,Postgresql,Count,Schema,Database Table,我试图计算数据库中所有表中的行数。因为我想要得到的答案必须区分不同的模式,所以我还考虑了特定表所在的模式 这非常有用,但事实证明我没有访问数据库中所有模式的权限 我知道我可以通过执行以下查询来检查特定表或架构的权限: select count(*) from ( SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name='data' and privilege_type

我试图计算数据库中所有表中的行数。因为我想要得到的答案必须区分不同的模式,所以我还考虑了特定表所在的模式

这非常有用,但事实证明我没有访问数据库中所有模式的权限

我知道我可以通过执行以下查询来检查特定表或架构的权限:

select count(*) from (
SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='data' and privilege_type = 'SELECT') as foo
以及检查输出是否等于或大于1

我目前的代码如下:

CREATE or replace function rowcount_all(schema_name text default 'public')
  RETURNS table(table_name_var text, cnt bigint) as
$$
declare
 table_name_var text;
begin
  for table_name_var in SELECT c.relname FROM pg_class c
    JOIN pg_namespace s ON (c.relnamespace=s.oid)
    WHERE c.relkind = 'r' AND s.nspname=schema_name
  loop
    if (
    select count(*) from (
    SELECT grantee, privilege_type 
    FROM information_schema.role_table_grants 
    WHERE table_name=table_name_var and privilege_type = 'SELECT') as foo
  ) >= 1 then 
    RETURN QUERY EXECUTE format('select cast(%L as text),count(*) from %I.%I',
       table_name_var, schema_name, table_name_var);
    end if;
  END loop;
end
$$ language plpgsql;
在执行以下查询时

WITH rc(schema_name,tbl) AS (
  select s.n,rowcount_all(s.n) from (values ('schema1'),
    ('schema2'), ('schema3'), ('schema4')) as s(n)
)
SELECT schema_name,(tbl).* FROM rc;
我收到一个错误,该错误为
error:relationship table1
的权限被拒绝,其中
table1
位于我无权访问的架构中。我假设IF语句中的逻辑某种程度上没有过滤掉我无权访问的表。

作为数据库元数据的SQL标准表示形式,如果您试图构建可移植的东西,它会很有用,但如果您只是试图管理Postgres服务器,它通常会有点笨拙

检查权限的最简单方法是使用。我相信这将只返回您能够查询的表:

select oid::regclass::text
from pg_class
where relkind = 'r'
  and relnamespace = schema_name::regnamespace
  and has_schema_privilege(relnamespace, 'USAGE')
  and has_any_column_privilege(oid, 'SELECT')
请注意,
拥有任何列的特权()
非常有用(与更明显的
拥有表的特权()
相比),因为您不需要对
选择计数(*)
拥有完整的表特权,只需访问其中一列即可(但不管是哪一列)

还请注意,
oid::regclass::text
将返回一个已经被引用并符合架构要求的表名(如果需要),因此您的
format()
调用可以使用一个简单的
%s
而不是
%I.%I

如果您可以处理一个大致的、稍微过时的记录计数,则可以通过查询上次运行的统计信息来完全绕过权限检查(并节省大量的表扫描):

select
  oid::regclass::text,
  reltuples
from pg_class
where relkind = 'r'
  and relnamespace = schema_name::regnamespace

@balkon16:更新了我的答案,以涵盖我忽略的一个边缘案例,以及一个您可能会发现有用的替代方法