暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

PostgreSQL问答-第20221117期

原创 多米爸比 2022-11-17
1524

Q1.数据库升级到PG 14之后,为什么很多应用软件连接失败?

问题描述

已经遇到过几次客户反馈PG数据库连接失败的问题,为什么只有升级到14,而其他版本没有出现呢?

问题解答

如果我们有关注14的新特性变化可以知道SCRAM-SHA-256现在已经是客户端认证的默认方式了,在此之前一直是MD5。其实从PG 10开始就已经支持SCRAM-SHA-256,只不过默认方式还是MD5,并且伴随PG 10的发布,配套的客户端驱动也有更新支持。

随着PG 15已经发布第二个小版本,越来越多客户开始使用PG 14,升级之后记得首先检查客户端驱动是否已更新支持SCRAM-SHA-256。

Q2.PG里如何自动记录行版本的修改时间?

问题描述

从DB2或MySQL迁移时会遇到ROW CHANGE TIMESTAMP或ON UPDATE CURRENT_TIMESTAMP的问题,在PG里如何实现呢?

问题解答

DB2或MySQL自动记录数据行修改的时间在PG里没有直接对应的特性,一种方式是通过触发器去实现的,另外一种方式是借助存储列的功能:

create table test1(
id int primary key, 
info text, 
crt_time timestamp not null default now(), 
mod_time timestamp GENERATED ALWAYS AS (wrapper_im_now(info)) stored
);  

上面wrapper_im_now函数的定义如下:

CREATE OR REPLACE FUNCTION public.wrapper_im_now(text)
 RETURNS timestamp with time zone
 LANGUAGE sql
 IMMUTABLE
AS $function$  
  select CURRENT_TIMESTAMP;  
$function$;

test1表info字段修改会触发自动更新存储列mod_time,如果还有其它字段也希望触发,可以微调修改上面的接口定义。

PG里存储列和生成列示例可扩展阅读这篇文章:
<<PostgreSQL标识列及存储列示例>>

Q3.PSQL如何自适应查询结果集?

问题描述

Oracle的SQL Plus操作都习惯先使用col name for来进行查询预设置,PG里是否有对应的设置呢?

问题解答

SQL Plus对应到PSQL,比较常见的方式是使用扩展模式竖排显示:

image.png

另外一种方式,直接用表名单列显示整行数据:
image.png

第三种方式,查看\pset相关参数,可以使用下面的两条命令来处理

\pset format wrapped
\pset columns 0

format在wrapped模式下设置columns,columns设置为0,可根据屏幕宽度自动调整,效果如下:

image.png

下面的图是拖动窗口之后的自适配效果:

image.png

Q4.如何获取序列的当前值?

问题描述

首次获取序列的值需要先调用nextval来获取值,跨session不能使用currval来调用当前值,难道必须使用nextval推进才能正常获取吗?

问题解答

PG 10中添加了pg_sequences视图,便于获取序列的动态信息,可以通过last_value来获取当前值。

postgres=# select last_value from pg_sequences 
            where sequencename='s2_id_seq';
 last_value 
------------
          1
(1 row)

也可以把序列当成表一样直接查last_value

postgres=# select last_value from s2_id_seq;
 last_value 
------------
          1
(1 row)

还可以使用pg_sequence_last_value函数

postgres=# select pg_sequence_last_value('s2_id_seq');
 pg_sequence_last_value 
------------------------
                      1
(1 row)

Q5.根据表名如何定位在哪些数据库的哪些schema下?

问题描述

需要根据表名确认一张表属于哪个database,哪个schema?

问题解答

PG中可以使用多个database,所以需要遍历所有db进行查找,语句如下:

for db in `psql --pset=pager=off -t -A -q -c 'select datname from pg_database where datname not in ($$template0$$, $$template1$$)'`
do
psql -d $db --pset=pager=off -q -c 'select current_database(),schemaname from pg_stat_user_tables where relname=$$mydb_tab1$$;'
done

实际查找时替换表名即可。

最后修改时间:2022-11-17 10:45:39
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论