2013-08-29 19 views
1

我正在使用以下查詢來發現(1)主鍵列和(2)列是否具有Postgresql 9.1中information_schema的缺省值。從information_schema查找Postgresql中的主鍵只有SELECT

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 

當數據庫所有者運行它工作正常,但是當我運行它的「只讀」的用戶(我需要在我的應用程序做的),它沒有返回數據。一些研究表明,問題在於information.table_constraints視圖;從文檔:

視圖table_constraints包含屬於當前用戶擁有或具有一些非SELECT權限的表的所有約束。

因此,爲了檢索table_constraints,我的登錄角色需要比表上的SELECT更多嗎?是否沒有辦法從information_schema獲取信息,而無需爲登錄角色提供寫入權限?

回答

2

使用pg_ *視圖而不是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 
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。這是一個巨大的差異,尤其是如果您的服務器負載較高時。