狙击手挑战
105.14M · 2026-03-12
你以为的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
Vite 凭什么比 Webpack 快50%?揭秘闪电构建背后的黑科技
我用 OpenClaw 搭了一套运营 Agent,每天自动生产内容、分发、追踪数据——独立开发者的运营平替
2026-03-12
2026-03-12