无需添加引号使PostgreSQL标识符区分大小写:MySQL迁移至PostgreSQL的SQL查询适配求助
解决PostgreSQL中混合大小写标识符查询的非手动方案
我之前迁移MySQL到PostgreSQL时也踩过这个大小写的坑,完全手动加引号确实太折磨人了,给你几个相对高效的方案:
方案1:批量脚本自动给查询标识符加引号
不用手动逐个修改查询,可以写个简单的脚本自动识别SQL里的表名、列名,给它们加上双引号。比如用Python的sqlparse库来解析SQL语句,遍历所有标识符节点,自动包裹引号。
举个简单的示例代码:
import sqlparse
from sqlparse.tokens import Token
def quote_identifiers(sql):
parsed = sqlparse.parse(sql)[0]
for token in parsed.flatten():
if token.ttype == Token.Name and not token.value.startswith('"'):
token.value = f'"{token.value}"'
return str(parsed)
# 测试示例
old_sql = "SELECT Table.Column FROM Table WHERE Table.Id = 1"
new_sql = quote_identifiers(old_sql)
print(new_sql) # 输出: SELECT "Table"."Column" FROM "Table" WHERE "Table"."Id" = 1
这个脚本能处理大部分常规查询,复杂的嵌套查询或特殊别名可能需要微调,但比手动修改效率高太多。你可以把所有旧查询批量跑一遍这个脚本,直接生成适配PostgreSQL的版本。
方案2:创建小写视图映射大写表
如果不想修改任何查询语句,可以在PostgreSQL里给每个带混合大小写的表创建一个小写的视图,把查询里的小写标识符映射到真实的大写表/列。
比如真实表是"Table",列是"Column",你可以创建视图:
CREATE VIEW table AS
SELECT "Column" AS column, "Id" AS id
FROM "Table";
这样旧查询SELECT table.column FROM table WHERE table.id = 1就能正常执行了。
如果表和列数量很多,完全可以批量生成创建视图的SQL,比如从information_schema里查询生成:
SELECT 'CREATE VIEW ' || lower(table_name) || ' AS SELECT ' ||
string_agg('"' || column_name || '" AS ' || lower(column_name), ', ') ||
' FROM "' || table_name || '";'
FROM information_schema.columns
WHERE table_schema = 'public' -- 替换成你的实际schema
GROUP BY table_name;
执行这个查询会生成所有表的视图创建语句,直接运行就能批量搞定。这个方案的好处是查询完全不用改,但要注意后续表结构变更时,视图也要同步更新。
方案3:检查pgloader的迁移配置(若未完成迁移)
如果你还在使用pgloader迁移数据,可以看看它的参数是否能帮你提前规避这个问题。pgloader有--quote-identifiers参数,迁移时会自动给表和列名加上双引号,不过你提到已经无法转换表列名为小写,应该已经完成了这一步,但如果迁移还没结束,可以确认下这个配置是否正确。
需要注意的是,PostgreSQL的标识符大小写规则是硬编码的:未加引号的标识符会被自动转换为小写,加引号的则保留原大小写。所以没有官方模块或配置能让PostgreSQL默认保留未加引号标识符的大小写,上面的方案都是绕开这个规则的实用办法。
内容的提问来源于stack exchange,提问作者Janne Annala




