62

给定表名,如何从 plpgsql 函数中提取主键列及其数据类型的列表?

4

10 回答 10

45

上面的查询非常糟糕,因为它真的很慢。

我会推荐这个官方版本:

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 = 'foo'::regclass AND 
  indrelid = pg_class.oid AND 
  nspname = 'public' AND 
  pg_class.relnamespace = pg_namespace.oid AND 
  pg_attribute.attrelid = pg_class.oid AND 
  pg_attribute.attnum = any(pg_index.indkey)
 AND indisprimary
于 2013-12-12T07:48:57.567 回答
35

要提供简单的 SQL,您可以列出主键列及其类型:

SELECT c.column_name, c.data_type
FROM information_schema.table_constraints tc 
JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name) 
JOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema
  AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
WHERE constraint_type = 'PRIMARY KEY' and tc.table_name = 'mytable';
于 2012-04-02T23:45:56.153 回答
27
\d tablename 

将为您提供主键信息以及其他与表相关的信息,例如所有列、它们的类型、关联的索引、约束、规则、触发器等。您可能不需要所有这些信息,但它是获取所有信息的最快方法详细信息一目了然,请在此处查看更多详细信息。

它返回如下内容:

    Table "public.tablename"
     Column |  Type   | Modifiers 
    --------+---------+-----------
     col1   | text    | not null
     col2   | numeric | 
     col3   | text    | 
     col4   | text    | 
     col5   | numeric | 
    Indexes:
        "tablename_pkey" PRIMARY KEY, btree (col1)
于 2019-07-07T17:49:49.870 回答
19

以下SQL语句对我有用:

SELECT a.attname
FROM   pg_index i
JOIN   pg_attribute a ON a.attrelid = i.indrelid
                     AND a.attnum = ANY(i.indkey)
WHERE  i.indrelid = 'tablename'::regclass
AND    i.indisprimary;

它直接取自这里

于 2017-02-21T14:25:30.880 回答
4

看一下pg_constraint系统表。或者information_schema.table_constraints查看您是否更愿意遵守 SQL 标准。

psql有关使用“-E”选项和类型连接到数据库的完整示例\d <some_table>- 您将看到描述表时使用的实际查询。

于 2009-08-01T00:51:01.003 回答
4

你真的只需要 2 个系统表:

  • pg_constraint - 告诉你哪些列(按编号)属于主键
  • pg_attribute - 将列号转换为列名

注意:系统表可能会在 PostgreSQL 版本之间发生变化,但这种情况并不经常发生(如果有的话,实际上很少发生)。与使用 information_schema.table_constraints 不同,您不需要任何特殊权限,只需在表上选择即可。(这在 Postgres 10.6 中测试过)

SELECT string_agg(a.attname, ', ') AS pk
FROM
    pg_constraint AS c
    CROSS JOIN LATERAL UNNEST(c.conkey) AS cols(colnum) -- conkey is a list of the columns of the constraint; so we split it into rows so that we can join all column numbers onto their names in pg_attribute
    INNER JOIN pg_attribute AS a ON a.attrelid = c.conrelid AND cols.colnum = a.attnum
WHERE
    c.contype = 'p' -- p = primary key constraint
    AND c.conrelid = '<schemaname>.<tablename>'::REGCLASS; -- regclass will type the name of the object to its internal oid
于 2019-04-02T09:55:33.833 回答
3
SELECT a.attname AS name, format_type(a.atttypid, a.atttypmod) AS type
FROM
    pg_class AS c
    JOIN pg_index AS i ON c.oid = i.indrelid AND i.indisprimary
    JOIN pg_attribute AS a ON c.oid = a.attrelid AND a.attnum = ANY(i.indkey)
WHERE c.oid = 'example'::regclass

输出:

 name |  type  
------+--------
 id   | bigint
于 2021-01-01T16:41:56.440 回答
1

注意列顺序与表的列顺序不同的索引。(即如果主键使用了第 3、2 和 1 列)

以下查询要复杂得多,但会以正确的顺序返回列。(删除“indisprimary”子句以获取表上所有索引的相同信息)

WITH ndx_list AS
(
    SELECT pg_index.indexrelid
      FROM pg_index, pg_class
     WHERE pg_class.relname = 'test_indices_table'
       AND pg_class.oid = pg_index.indrelid
       AND pg_index.indisprimary
), ndx_cols AS
(
   SELECT pg_class.relname AS index_name, UNNEST(i.indkey) AS col_ndx, i.indisunique, i.indisprimary
     FROM pg_class, pg_index i
    WHERE pg_class.oid = i.indexrelid
      AND pg_class.oid IN (SELECT indexrelid FROM ndx_list)
)
  SELECT ndx_cols.index_name, ndx_cols.indisunique, ndx_cols.indisprimary,
         a.attname, format_type(a.atttypid, a.atttypmod), a.attnum
    FROM pg_class c, pg_attribute a
    JOIN ndx_cols ON (a.attnum = ndx_cols.col_ndx)
   WHERE c.oid = 'test_indices_table'::regclass
     AND a.attrelid = c.oid
于 2015-02-23T19:00:45.597 回答
1
SELECT
   conrelid::regclass AS table_from,
   conname,
   pg_get_constraintdef ( c.oid )
FROM
   pg_constraint c
   JOIN pg_namespace n ON n.oid = c.connamespace
WHERE
   contype IN ( 'f', 'p ' )
   AND conrelid::regclass::TEXT IN ( 'foo' )

ORDER BY
   conrelid::regclass::TEXT,
   contype DESC
于 2019-01-29T08:29:59.547 回答
0

使用以下方法保留列顺序generate_subscripts

SELECT
  a.attname,
  format_type(a.atttypid, a.atttypmod) 
FROM
  pg_attribute a
  JOIN (SELECT *, GENERATE_SUBSCRIPTS(indkey, 1) AS indkey_subscript FROM pg_index) AS i
    ON
      i.indisprimary
      AND i.indrelid = a.attrelid
      AND a.attnum = i.indkey[i.indkey_subscript]
WHERE
  a.attrelid = 'your_table'::regclass
ORDER BY
  i.indkey_subscript
于 2016-10-03T01:34:43.633 回答