获取Postgres表列的默认值?
获取Postgres表列的默认值?
我正在寻找一种方法来运行查询,以查找Postgres中表的列的默认值。例如,如果我使用以下查询创建了一个表:\n**编辑注:我修复了表的定义,因为它对问题没有影响。\n
CREATE TABLE mytable ( integer int DEFAULT 2, text varchar(64) DEFAULT 'I am default', moretext varchar(64) DEFAULT 'I am also default', unimportant int );
\n我需要一个查询以某种格式告诉我,integer
的默认值是2,text
的默认值是\'I am default\',moretext
的默认值是\'I am also default\'。查询结果可以包括任何其他没有默认值的列的任何值,即unimportant
对我的目的来说不重要,根本不重要。
问题的出现原因:
1. 有时候即使使用了`NOT a.attisdropped`条件,仍然会得到类似于"........pg.dropped.30......."的列名,但这种情况不一致,只能通过循环遍历结果并检查列名来解决。
2. 返回的默认值有时带有类型转换,例如`'I am default'::character varying`,但当将其填充到Web表单输入值时,这种类型转换是无效的。没有想到好的方法去除类型转换后缀,只能使用`.replace(/::.*/, '')`这种不够健壮的方式。相信Erwin可以找到一种神奇的方式来使用返回的值并利用`a.atttypid`列来获取正确的数据类型。
解决方法:
作者回到了之前使用的方法:
BEGIN; INSERT INTO mytable DEFAULT VALUES RETURNING *; ROLLBACK;
需要注意的一点是,任何`SERIAL`列都会自增。如果它只是一个表索引,那可能没有关系,只要它是唯一的。否则,这是一个无法接受的问题。
另一件需要注意的事情是任何`TRIGGER AFTER/BEFORE INSERT`,即使`INSERT`被回滚,触发器也会触发(尽管我认为触发器函数所做的任何更改都会被回滚)。
在Postgres中,系统目录是真相的来源。可以通过查询系统目录来获取表列的默认值。以下是一个示例查询代码:
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`转换,它考虑了当前的`search_path`设置。如果列名没有加上模式限定符(为了确保准确性,应该加上限定符),可能无法得到预期的结果。
上面的查询代码中没有包含`pg_class`,因为我们已经有了表的OID,这样可以提高查询速度。
为什么之前的答案不可行?因为之前的查询代码存在一些问题:
- 从某个博客中复制的,但是没有提供出处,读者需要被警告。
- `pg_atttribute`中的拼写错误,可以轻易修复。
- 如果请求的列没有设置默认值,查询结果不会返回任何行。可以使用`LEFT JOIN pg_attrdef ON ..`,这样无论是否设置了默认值,都会返回一行结果。如果没有默认值,则返回`NULL`,这实际上是正确的结果,因为`NULL`就是默认值。
- 如果在`WHERE`子句中移除`attname`,则只会返回具有默认值的列,而不会返回其他列。还需要在`SELECT`列表中添加`attname`,否则无法知道哪个列有默认值。
- 查询还会返回已经被删除的列的默认值,这是错误的。
- 最重要的是,查询没有考虑模式名称,因此在Postgres数据库中可以存在任意数量的`table1.col1`,它们位于不同的模式中。如果有多个列有默认值,查询结果会返回多个值。如果你所想的列没有默认值,但是其他模式中的另一个列有默认值,你将被误导而不会知道这一点。
- 最后,最近的PostgreSQL版本已经从`pg_attrdef`中删除了`adsrc`列,因为它是多余的、已弃用的,并且在PostgreSQL中没有使用。
总结一下,从某个博客中复制的代码缺乏洞察力,容易出错。
如果想将查询封装成一个函数,返回值的数据类型应该是什么?由于返回值取决于请求的列的类型,所以可以使用`text`数据类型。
以上就是如何在Postgres中获取表列的默认值的问题的原因和解决方法。通过查询系统目录,我们可以获取到表列的默认值。
在Postgres中,有时需要获取表列的默认值。下面是一个解决方法以及出现该问题的原因。
问题的原因:
在某些情况下,我们可能需要知道表中列的默认值。这可能是为了验证数据的完整性,或者在插入新行时提供默认值。然而,Postgres并没有直接提供获取表列默认值的函数或命令。
解决方法:
我们可以使用信息模式(information schema)来获取表列的默认值。下面的代码展示了如何在Postgres中获取表列的默认值:
SELECT column_name, column_default FROM information_schema.columns WHERE (table_schema, table_name) = ('public', 'mytable') ORDER BY ordinal_position;
这个查询将返回指定表中所有列的默认值。具体来说,它返回了列的名称(column_name)和默认值(column_default)。通过将"public"和"mytable"替换为相应的模式(schema)和表(table)名称,我们可以在任何Postgres数据库中使用这个查询。
需要注意的是,这种方法在任何SQL数据库系统中都适用,因为它使用了通用的信息模式。
虽然在Postgres中没有直接的方法来获取表列的默认值,但使用信息模式可以轻松地解决这个问题。通过查询信息模式中的列(column)和默认值(default),我们可以获取到所需的信息。在任何SQL数据库系统中,这个方法都是有效的,因为信息模式是通用的。