PostgreSQL "DESCRIBE TABLE"

2160
在PostgreSQL中使用psql命令执行类似于Oracle的DESCRIBE TABLE的等效操作,应该怎么做?

25个回答

3151

尝试在psql命令行工具中执行以下操作:

\d+ tablename

查看手册获取更多信息。


11
我原本接受了devinmoore的答案,但我更喜欢这个。它不仅描述了表格,还显示了元数据,如列描述和是否有任何OID。 - Mr. Muskrat
38
+ 在这里非常关键,因为PostgreSQL 9仅在使用\d+ table_name时才提供视图的详细描述,而不是简单的\d table_name - nessur
13
在使用pgAdmin调用PostgreSQL 9.1时,\d命令无法正常工作。下面Vinko的回答适用于更多情况。 - hello_earth
14
psql -E 命令很方便,可以得到实现 \d+ 等命令的 SQL 代码(用于在 psql 提示符之外使用)。 - bsb
28
错误:"did not find any relation named"。这意味着你需要将表名放在双引号中。显然,如果没有双引号,Postgres会自动转为小写字母,导致找不到你的表。希望这能帮助其他遇到这个问题的人们。 :) - amurrell
显示剩余5条评论

917

除了 PostgreSQL 的方式(如 \d 'something' 或 \dt 'table' 或 \ds 'sequence' 等),

还有一种符合 SQL 标准的方法,可以参考这里

select column_name, data_type, character_maximum_length, column_default, is_nullable
from INFORMATION_SCHEMA.COLUMNS where table_name = '<name of table>';

它被许多数据库引擎支持。


25
在'表'中选择列名、数据类型和字符最大长度:使用INFORMATION_SCHEMA.COLUMNS语句。 - SO Stinks
8
当你使用早于8.4版本的psql以及晚于8.4版本的服务器时,这比\d命令更有用 - 因为\d命令不兼容。 - beldaz
31
这个命令也可以在RedShift上运行,但\d+则不行。这是我个人认为的最佳答案。 - New Alexandria
8
很棒,虽然对于Postgres,我会加上模式名称。 - ffflabs
4
这只列出了最少信息的列。\d+会为表提供完整的DDL,包括:默认值、可空性、下一个值、精度、主键、外键、索引、检查约束以及来自其他表的FK。 - bradw2k
显示剩余7条评论

80
如果你想从查询中获取而不是从psql中获取,你可以查询目录模式。这是一个复杂的查询,可以实现这个功能。
SELECT  
    f.attnum AS number,  
    f.attname AS name,  
    f.attnum,  
    f.attnotnull AS notnull,  
    pg_catalog.format_type(f.atttypid,f.atttypmod) AS type,  
    CASE  
        WHEN p.contype = 'p' THEN 't'  
        ELSE 'f'  
    END AS primarykey,  
    CASE  
        WHEN p.contype = 'u' THEN 't'  
        ELSE 'f'
    END AS uniquekey,
    CASE
        WHEN p.contype = 'f' THEN g.relname
    END AS foreignkey,
    CASE
        WHEN p.contype = 'f' THEN p.confkey
    END AS foreignkey_fieldnum,
    CASE
        WHEN p.contype = 'f' THEN g.relname
    END AS foreignkey,
    CASE
        WHEN p.contype = 'f' THEN p.conkey
    END AS foreignkey_connnum,
    CASE
        WHEN f.atthasdef = 't' THEN pg_get_expr(d.adbin, d.adrelid)
    END AS default
FROM pg_attribute f  
    JOIN pg_class c ON c.oid = f.attrelid  
    JOIN pg_type t ON t.oid = f.atttypid  
    LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum  
    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace  
    LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)  
    LEFT JOIN pg_class AS g ON p.confrelid = g.oid  
WHERE c.relkind = 'r'::char  
    AND n.nspname = '%s'  -- Replace with Schema name  
    AND c.relname = '%s'  -- Replace with table name  
    AND f.attnum > 0 ORDER BY number
;
这个东西挺复杂的,但它确实展示了 PostgreSQL 系统目录的强大和灵活性,应该能帮助你掌握 pg_catalog。记得在查询中替换掉 %s 的部分。第一个是模式(Schema),第二个是表名。

4
这个解决方案的一个优点是format_type()函数将包含附加到类型上的任何修饰符,例如numeric(6,2);而information_schema.columns只会报告numeric的基本类型。 - Eli Collins
3
如何将数据类型与大小分开?例如将 | character varying(50) | 拆分成两列:| character varying | 50 |。 - ivanceras
1
在v12中失败,因为pg_attrdef.adsrc不再存在。 - RonJohn
@RonJohn,我已经更新到v12版本了,只需将d.adsr替换为pg_get_expr(d.adbin, d.adrelid)就可以了。 - undefined

68

你可以使用psql斜线命令完成此操作:

 \d myTable describe table

它也适用于其他对象:

 \d myView describe view
 \d myIndex describe index
 \d mySequence describe sequence

来源:faqs.org


49

这应该是解决方案:

SELECT * FROM information_schema.columns
WHERE table_schema = 'your_schema'
   AND table_name   = 'your_table'

2
这是一个更完整的答案。如果您没有收到任何行,请尝试这个方法。当有疑问时,必须始终提供模式名称。 - Vijay Kumar

46

\d table是描述数据库表结构等信息的psql命令,相当于DESCRIBE TABLE

更多细节请参考PostgreSQL手册中关于psql部分的内容。


3
此外,对于像我这样从MySQL转来的人来说,psql数据库选择是\c databasename而不是use databasename。如果不先使用\c databasename,则\d tablename将产生“找不到关系”的消息,仅此而已。 - Ville
你也可以使用\d databasename.tablename。如果名称不全是小写,则需要适当引用,即\d "DatabaseName"."TableName" - ddevienne

23

您可以使用带有星号的\d *搜索模式 *来查找与您感兴趣的搜索模式匹配的表。


这正是我一直在寻找的——如何描述表的子集。值得注意的是,如果您的表具有大写字母,则语法为\d *"<SubString>"*。也就是说,双引号必须位于星号内部。不过,如果您只想要表的列表,则应使用\dt - Randall
这匹配序列、索引以及表格。 - user4104817

19

除了你已经找到的命令行\d+ <table_name>之外,你还可以使用information-schema来查找列数据,使用info_schema.columns

SELECT *
FROM info_schema.columns
WHERE table_schema = 'your_schema'
AND table_name   = 'your_table'

9
“FROM info_schema.columns”对我无效,我不得不使用“from information_schema.columns”,不确定这是你答案中的一个打字错误还是我的实现问题。 - user27874

16

使用以下SQL语句

SELECT DATA_TYPE 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'tbl_name' 
AND COLUMN_NAME = 'col_name'

如果你替换tbl_name和col_name,它会显示你所寻找的特定列的数据类型。


3
这是2008年这篇回答所说的。 - Quentin
@Quentin-它们之间有区别.. 上面的2008解决方案描述了整个表的列名、数据类型和字符最大长度。而我的 - 所提供的解决方案 - 只显示模式列的数据类型。运行两者并检查。它们是不同的。这里的所有解决方案都是解决问题的不同方式。用户可以出于不同的原因使用这些解决方案。 - Mr.Tananki

15
你可以使用这个:
SELECT attname 
FROM pg_attribute,pg_class 
WHERE attrelid=pg_class.oid 
AND relname='TableName' 
AND attstattarget <>0; 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,