无需添加引号使PostgreSQL标识符区分大小写:MySQL迁移至PostgreSQL的SQL查询适配求助
我之前迁移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




