在仅使用SELECT的information_schema中查找Postgresql中表的主键

时间:2013-08-29 17:03:07

标签: postgresql permissions primary-key information-schema

我使用以下查询来发现(1)主键列和(2)列是否具有Postgresql 9.1中information_schema的默认值。

SELECT kcu.column_name, (c.column_default is not null) AS has_default 
FROM information_schema.key_column_usage kcu 
JOIN information_schema.table_constraints tc ON tc.constraint_name = kcu.constraint_name 
JOIN information_schema.columns c on c.column_name = kcu.column_name and c.table_name = kcu.table_name  
WHERE tc.constraint_type = 'PRIMARY KEY' AND kcu.table_name like :tablename

它作为数据库所有者运行时工作正常,但当我作为“只读”用户(我需要在我的应用程序中执行)运行它时,它不返回任何数据。一些研究表明问题是信息.table_constraints视图;来自文档:

  

view table_constraints包含属于当前用户拥有的表或具有某些非SELECT权限的所有约束。

因此,为了检索table_constraints,我的登录角色需要的不仅仅是表上的SELECT吗?如果没有给登录角色提供写入权限,是否无法从information_schema获取信息?

2 个答案:

答案 0 :(得分:2)

使用pg_ * views而不是information_schema视图。
pg_ * views显示所有授予权限的信息。

尝试此查询:

select
    t.relname as table_name,
    i.relname as index_name,
    a.attname as column_name,
    d.adsrc   as default_value
from
    pg_class t
    join pg_attribute a on a.attrelid = t.oid
    join pg_index ix    on t.oid = ix.indrelid AND a.attnum = ANY(ix.indkey)
    join pg_class i     on i.oid = ix.indexrelid
    left join pg_attrdef d on d.adrelid = t.oid and d.adnum = a.attnum  
where
    t.relkind = 'r'
    and t.relname in ( 'aa', 'bb', 'cc' )
order by
    t.relname,
    i.relname,
    a.attnum;

查询结果的示例:

create table aa(
  x int primary KEY
);

create table bb(
  x int default 1,
  constraint pk primary key ( x )
);

create table cc(
  x int default 20,
  y varchar(10) default 'something',
  constraint cc_pk primary key ( x, y )
);

 table_name | index_name | column_name |         default_value
------------+------------+-------------+--------------------------------
 aa         | aa_pkey    | x           |
 bb         | pk         | x           | 1
 cc         | cc_pk      | x           | 20
 cc         | cc_pk      | y           | 'something'::character varying

答案 1 :(得分:0)

这是正确的,官方postgresql查询在

之下

http://wiki.postgresql.org/wiki/Retrieve_primary_key_columns

如果需要架构,则查询如下

SELECT               
  pg_attribute.attname, 
  format_type(pg_attribute.atttypid, pg_attribute.atttypmod) 
FROM pg_index, pg_class, pg_attribute, pg_namespace 
WHERE 
  pg_class.oid = 'MY TABLE'::regclass AND 
  indrelid = pg_class.oid AND 
  nspname = 'MY CLASS' AND 
  pg_class.relnamespace = pg_namespace.oid AND 
  pg_attribute.attrelid = pg_class.oid AND 
  pg_attribute.attnum = any(pg_index.indkey)
  AND indisprimary

差异可达6000~7000倍。 pg_经常在0.56ms运行,其中基于模式的一个可以运行6500ms。这是一个巨大的差异,特别是如果您的服务器负载很高。