Sql 获取Postgres中表列的默认值?

Sql 获取Postgres中表列的默认值?,sql,postgresql,default,Sql,Postgresql,Default,我正在寻找一种方法来运行查询,以查找Postgres中表列的默认值。例如,如果我使用以下查询创建了一个表: **编者按:我修复了表定义,因为它对问题没有影响 我需要一个查询,以某种格式告诉我,integer的默认值是2,text是“我是默认值”,而moretext是“我也是默认值”。查询结果可以包括没有默认值的任何其他列的任何值,即,不重要对我来说不重要,根本不重要 SELECT adsrc as default_value FROM pg_attrdef pad, pg_atttribut

我正在寻找一种方法来运行查询,以查找Postgres中表列的默认值。例如,如果我使用以下查询创建了一个表:

**编者按:我修复了表定义,因为它对问题没有影响

我需要一个查询,以某种格式告诉我,
integer
的默认值是2,
text
是“我是默认值”,而
moretext
是“我也是默认值”。查询结果可以包括没有默认值的任何其他列的任何值,即,
不重要
对我来说不重要,根本不重要

 SELECT adsrc as default_value
 FROM pg_attrdef pad, pg_atttribute pat, pg_class pc
 WHERE pc.relname='your_table_name'
     AND pc.oid=pat.attrelid AND pat.attname='your_column_name'
     AND pat.attrelid=pad.adrelid AND pat.attnum=pad.adnum
我在其中一个博客上找到了对postgresql的查询。你可以试试这个来检查它是否有效。要获取所有列的值,可以尝试从where子句中删除
和pat.attname='your\u column\u name'

只需键入“\d table\u name”命令,它就会显示有关 表,例如列的默认值

--创建表格

skytf=> CREATE TABLE mytable (
skytf(>     a integer DEFAULT 2,
skytf(>     b varchar(64)  DEFAULT 'I am default',
skytf(>     c varchar(64)  DEFAULT 'I am also default'
skytf(> );
CREATE TABLE
--显示表格信息

skytf=> \d mytable
                              Table "skytf.mytable"
 Column |         Type          |                   Modifiers                    
--------+-----------------------+------------------------------------------------
 a      | integer               | default 2
 b      | character varying(64) | default 'I am default'::character varying
 c      | character varying(64) | default 'I am also default'::character varying
是博士后真理的源泉:

SELECT pg_get_expr(d.adbin, d.adrelid) AS default_value
FROM   pg_catalog.pg_attribute    a
LEFT   JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid,  d.adnum)
WHERE  NOT a.attisdropped           -- no dropped (dead) columns
AND    a.attnum   > 0               -- no system columns
AND    a.attrelid = 'myschema.mytable'::regclass
AND    a.attname  = 'mycolumn';
LEFT JOIN
只要列存在,就会保证结果。如果没有默认值,则会得到
NULL
——这恰好是默认值。而且几乎总是正确的。但请看:

要在没有默认值的情况下排除列,请改用
JOIN
,并准备偶尔不获取行

特殊类型转换
::regclass
考虑
搜索路径的当前设置。对于不符合模式限定的名称(当然,您应该这样做!),您可能会也可能不会得到预期的结果。见下面的反驳。相关的:

一旦我们有了表的OID,就不需要包括
pg_类
。没有它,速度更快

为什么第一个答案不行 这几乎是正确的,但并不完全正确。有几个问题。我把它复制到这里以备将来参考请勿使用此项

SELECT adsrc as default_value
 FROM pg_attrdef pad, pg_atttribute pat, pg_class pc
 WHERE pc.relname='your_table_name'
     AND pc.oid=pat.attrelid AND pat.attname='your_column_name'
     AND pat.attrelid=pad.adrelid AND pat.attnum=pad.adnum
  • 从某个博客上抄来的。很好,已经提到了,但是应该添加源代码。阅读该博客的人需要得到警告

  • pg\u attribute
    中的打字错误-易于修复

  • 如果没有为请求的列指定默认值,则不返回任何行。最好在..
上设置一个
左连接pg_attrdef,这样,如果列存在,您总是会得到一个结果行。如果没有默认值,它将为NULL,这实际上是正确的结果,因为
NULL
是默认值

  • 如果从WHERE子句中删除
    attname
    ,则只能获取实际具有默认值的列的值。不适合其他人。您需要将
    attname
    添加到选择列表中,否则您将不知道是哪一列

  • 查询还将返回已删除的列的默认值,即错误。阅读关于这个问题的文章

  • 最重要的是:查询可能会给出完全错误的结果,因为它没有考虑架构名称。postgres数据库中可以有任意数量的
    table1.col1
    :在各种模式中。如果有多个默认值,则会得到多个值。如果您心目中的列没有默认值,但另一个模式中的另一个列有默认值,那么您将被愚弄,永远不会知道它

  • 最后一点:在最新的PostgreSQL版本中,commit fe5038236c从
    pgêattrdef
    中删除了
    adsrc
    列,因为它在PostgreSQL中是多余的、不推荐使用的和未使用的


  • 总而言之:一些没有洞察的博客的C/p出现了危险的错误。

    使用信息模式:

    SELECT column_name, column_default
    FROM information_schema.columns
    WHERE (table_schema, table_name) = ('public', 'mytable')
    ORDER BY ordinal_position;
    
     column_name │             column_default             
    ─────────────┼────────────────────────────────────────
     integer     │ 2
     text        │ 'I am default'::character varying
     moretext    │ 'I am also default'::character varying
     unimportant │ 
    (4 rows)
    
    在模式命名之前,这应该适用于任何SQL数据库系统。

    我喜欢,但有一些困难:

  • 有时我会得到列名“……pg.dropped.30……”等,即使有
    而不是a.attisdropped
    限定。这是不一致的,我不得不循环检查结果并检查列名
  • 返回的默认值有时会附加一个强制转换,例如,
    'I am default':character variabling
    ,当它们被填充到web表单输入值中时,该转换不起作用。如果不执行
    .replace(/::..*/,'')
    之类的操作,我想不出删除强制转换后缀的好方法,因为这样做不够健壮。我打赌Erwin可以想出一些神奇的方法来获取返回值,并使用
    a.atttypid
    列来获取正确的数据类型
  • 所以我回到了我以前做的事情:

    BEGIN;
    INSERT INTO mytable DEFAULT VALUES RETURNING *;
    ROLLBACK;
    
    这里需要注意的一点是,任何
    SERIAL
    列都将递增。如果它只是一个表索引,那么只要它是唯一的,这可能并不重要。否则它就是一个交易破坏者


    另一件需要注意的事情是插入后/插入前的任何
    触发器,即使
    INSERT
    回滚也会触发(我认为触发器函数所做的任何更改都会回滚)。

    我正在花一些时间尝试处理pg_目录表。我假设这些名字都是从那些需要单独雕刻字母的日子里回来的,因此非常昂贵;-)不管怎样,这都是生活中的事实。我想获得一列的默认值,并运行到这个线程中。我看到有人提到希望将Erwin Brandstetter的代码作为函数。我已经把它包好了,我想我应该把它添加到档案中:

    CREATE OR REPLACE FUNCTION data.column_default (qualified_name text, column_name text)
      RETURNS text
     AS $$
    
    SELECT d.adsrc AS default_value -- A human-readable representation of the default value, already typed as text.
    FROM   pg_catalog.pg_attribute a
    LEFT   JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum)
                                         = (d.adrelid,  d.adnum)
    WHERE  NOT a.attisdropped   -- no dropped (dead) columns
    AND    a.attnum > 0         -- no system columns
    AND    a.attrelid = qualified_name::regclass
    AND    a.attname = column_name;
    
    $$ LANGUAGE sql;
    
    ALTER FUNCTION data.column_default (qualified_name text, column_name text) OWNER TO user_bender;
    
    我使用的代码(可能是不人道的方式)如下:

    从这里我想我会写一个观点,等等,一旦我更好地知道我真正想要的是什么。现在,我使用CTE作为临时视图:

    with attributes as
    (select pg_class.relnamespace::regnamespace as schema_name,
            attrelid::regclass as parent_name,
            attname,
           format_type(atttypid, atttypmod) as data_type,
           column_default(attrelid::regclass::text,attname),
           attnum
    
     from pg_attribute
     left join pg_class on (pg_class.oid = pg_attribute.attrelid::regclass)
    )
    
    select *
      from attributes
     where parent_name::text = 'sales'
    
    更正、改进和建议都是受欢迎的……我刚刚对pg_目录有了新的认识。

    他问我如何查询def
    select pg_class.relnamespace::regnamespace as schema_name,
            attrelid::regclass as parent_name,
            attname,
           format_type(atttypid, atttypmod) as data_type,
           column_default(attrelid::regclass::text,attname),
           attnum
    
     from pg_attribute
     left join pg_class on (pg_class.oid = pg_attribute.attrelid::regclass)
    
    with attributes as
    (select pg_class.relnamespace::regnamespace as schema_name,
            attrelid::regclass as parent_name,
            attname,
           format_type(atttypid, atttypmod) as data_type,
           column_default(attrelid::regclass::text,attname),
           attnum
    
     from pg_attribute
     left join pg_class on (pg_class.oid = pg_attribute.attrelid::regclass)
    )
    
    select *
      from attributes
     where parent_name::text = 'sales'