如何在where子句中使用列默认值来标识默认值



我试图写一个查询,告诉表a.t中名为s的列是否有其默认值(这是一个非常大的base64字符串)。所以我试了:

SELECT 1 FROM a.t WHERE s = (
   SELECT column_default FROM information_schema.columns
   WHERE (table_schema, table_name, column_name) = ('a', 't', 's'))
   AND uname = 'joe';

没有工作,所以我注意到information_schema.columns的结果有一些常规查询没有的东西:

SELECT column_default FROM information_schema.columns
WHERE (table_schema, table_name, column_name) = ('a', 't', 's');
column_default | 'data:image/png;base64,iVBO...QmCC'::text

SELECT s FROM a.t WHERE uname = 'joe';
s | data:image/png;base64,iVBO...QmCC

注意没有引号和显式强制转换。
这就是不匹配的原因吗?列s定义为类型text
如何更改查询,以便测试列值与其默认值之间的相等性?

从信息模式(或我的解决方案中的系统编目)检索到的只是一个表示表达式的字符串文字。您需要实际执行它来获得。它可以是一个简单的强制转换,比如任何其他表达式。这就是需要动态SQL的地方。(或者根据第一个查询的结果在客户端连接第二个查询)

相关答案中的详细解释:
使用PostgreSQL 9.3在CTE UPSERT中生成默认值
(您还可以在那里找到不使用动态SQL的替代路由的说明)

DO语句实现了这个目标。

DO
$do$
DECLARE
   _data text := 'data:image/png;base64,iVBO...QmCC';
   _answer bool;
BEGIN
EXECUTE (
   SELECT format('SELECT %s = $1', d.adsrc)
   FROM   pg_attribute a 
   JOIN   pg_attrdef   d ON (d.adrelid, d.adnum) = (a.attrelid, a.attnum)
   WHERE  a.attrelid = 'a.t'::regclass   -- schema.table
   AND    a.attname = 's'
   )
USING  _data
INTO   _answer;
RAISE NOTICE '%', answer;
END
$do$;
为了重复使用,我将它包装到一个plpgsql函数中。有很多相关的答案。

还要注意,列默认值可能具有副作用,例如增加序列。不是在这个特殊的情况下,但通常我建议在执行之前检查默认的

最新更新