你以为的PostgreSQL支持的表名最长长度是多少?256个字符?512个字符?

这里先卖个关子。

大家是否还记得之前流传的Linux中 rm -rf ${LOG_DIR}/命令的一个梗,由于未传参LOG_DIR变成了空值,于是执行的命令就变成了rm -rf /,然后服务器根目录就被删除了个干干净净。

我也犯了类似的错误,我要把一个过期的日志表给删除,由于表名超长了,并且被截断执行了,导致不该删除的表也被删除了。

模拟重现步骤如下:

第一步

创建模拟的正式表

-- 正式表建表语句
create table t_loooooooooooooooooooooooooooooooooooooooooong_name (name varchar(10));

第二步

将正式表重命名为备份表。

alter table t_loooooooooooooooooooooooooooooooooooooooooong_name rename to t_loooooooooooooooooooooooooooooooooooooooooong_name_bak_20260303;

执行时,你会发现,居然成功执行了。可是,再仔细一看,怎么还有提示:

第三步

根据备份表,重建一张正式表。你猜,这一步会成功执行吗?

答案是会的,并且会出现和第二步一样的提示。

create table t_loooooooooooooooooooooooooooooooooooooooooong_name (like t_loooooooooooooooooooooooooooooooooooooooooong_name_bak_20260303 including all);

第四步,重要的一步来了

假设我要滚动删除20260302那天的备份表,这里有一个隐含逻辑是20260302暂时还不存在,因为这是个新逻辑。

执行下面的SQL命令:

drop table t_loooooooooooooooooooooooooooooooooooooooooong_name_bak_20260302;

结果你应该能想到,又被截断执行了。并且把表t_loooooooooooooooooooooooooooooooooooooooooong_name_bak_202603删除了。也就是说,这个表刚刚备份出来就被删除了。

结论

来看一下,截断后的表名有多长。测试SQL如下:

select length('t_loooooooooooooooooooooooooooooooooooooooooong_name_bak_202603');

length|
------+
    63|

想不到吧,只有63个字符。

总结

关于这个特性,官方文档Identifiers and Key Words一节是有说明的,原文如下:

大意是标识符字节数不超过 NAMEDATALEN-1,具体是多少?就是 64-1=63

需要注意的是,原文中提及了对于多字节字符,比如中文名称,肯定达不到63,因为是按字节数算的。

我可以修改配置吗?增大范围。

不好意思,改不了,这个是编译期常量。如果你要自己编译一个版本是可以的。上面的原文引用已经列出的源码的修改位置了。

注意:官方说的是标识符,没说表名。也就是说类似,字段名、视图名等等都是适用的。

参考

PostgreSQL: Documentation: 18: 4.1. Lexical Structure

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com