编辑:所以,我写了下面的查询然后想......“等等,Postgresql 要求外键目标必须有唯一的索引。”所以我想我误解了你的意思?您可以使用以下查询来检查您的外键的 source 是否具有索引,方法是将“conrelid”替换为“confrelid”,将“conkey”替换为“confkey”(是的,是的,在查询...)
好吧,我想应该可以通过系统目录...像往常一样,系统目录的最佳指南是使用 psql 并执行“\set ECHO_HIDDEN 1”,然后查看它生成的 SQL有趣的“\d”命令。这是用于查找表的外键的 SQL ("\d tablename"):
-- $1 is the table OID, e.g. 'tablename'::regclass
SELECT conname, conrelid::pg_catalog.regclass,
pg_catalog.pg_get_constraintdef(c.oid, true) as condef
FROM pg_catalog.pg_constraint c
WHERE c.confrelid = $1 AND c.contype = 'f' ORDER BY 1;
似乎 pg_constraint 有列 conkey 和 confkey 看起来它们可能是定义键的列号。 confkey 可能是外表中的列号,因为它对于外键只有非空值。另外,我花了一段时间才意识到这是显示外键引用给定表的 SQL。这就是我们想要的。
所以这个查询显示数据开始成形:
select confrelid, conname, column_index, attname
from pg_attribute
join (select confrelid::regclass, conname, unnest(confkey) as column_index
from pg_constraint
where confrelid = 'ticket_status'::regclass) fkey
on fkey.confrelid = pg_attribute.attrelid
and fkey.column_index = pg_attribute.attnum
我将使用像 unnest 这样的 8.4 功能...如果没有你也许可以相处。
我最终得到:
select pg_index.indexrelid::regclass, 'create index ' || relname || '_' ||
array_to_string(column_name_list, '_') || '_idx on ' || confrelid ||
' (' || array_to_string(column_name_list, ',') || ')'
from (select distinct
confrelid,
array_agg(attname) column_name_list,
array_agg(attnum) as column_list
from pg_attribute
join (select confrelid::regclass,
conname,
unnest(confkey) as column_index
from (select distinct
confrelid, conname, confkey
from pg_constraint
join pg_class on pg_class.oid = pg_constraint.confrelid
join pg_namespace on pg_namespace.oid = pg_class.relnamespace
where nspname !~ '^pg_' and nspname <> 'information_schema'
) fkey
) fkey
on fkey.confrelid = pg_attribute.attrelid
and fkey.column_index = pg_attribute.attnum
group by confrelid, conname
) candidate_index
join pg_class on pg_class.oid = candidate_index.confrelid
left join pg_index on pg_index.indrelid = confrelid
and indkey::text = array_to_string(column_list, ' ')
好的,这个怪物打印出候选索引命令并尝试将它们与现有索引匹配。因此,您可以简单地在末尾添加“where indexrelid is null”以获取创建似乎不存在的索引的命令。
这个查询不能很好地处理多列外键;但恕我直言,如果您使用这些,那您就应该遇到麻烦。
LATER EDIT:这是在顶部放置建议编辑的查询。因此,这显示了在作为外部来源的列上创建不存在的索引的命令键(不是它的目标)。
select pg_index.indexrelid::regclass, 'create index ' || relname || '_' ||
array_to_string(column_name_list, '_') || '_idx on ' || conrelid ||
' (' || array_to_string(column_name_list, ',') || ')'
from (select distinct
conrelid,
array_agg(attname) column_name_list,
array_agg(attnum) as column_list
from pg_attribute
join (select conrelid::regclass,
conname,
unnest(conkey) as column_index
from (select distinct
conrelid, conname, conkey
from pg_constraint
join pg_class on pg_class.oid = pg_constraint.conrelid
join pg_namespace on pg_namespace.oid = pg_class.relnamespace
where nspname !~ '^pg_' and nspname <> 'information_schema'
) fkey
) fkey
on fkey.conrelid = pg_attribute.attrelid
and fkey.column_index = pg_attribute.attnum
group by conrelid, conname
) candidate_index
join pg_class on pg_class.oid = candidate_index.conrelid
left join pg_index on pg_index.indrelid = conrelid
and indkey::text = array_to_string(column_list, ' ')
where indexrelid is null
我的经验是,这并不是那么有用。它建议为确实不需要索引的参考代码等创建索引。