TypeORM 0.3.6执行迁移运行原生SQL报IF语法错误咨询
TypeORM 0.3.x迁移报
IF位置语法错误解决方案 核心结论
- TypeORM 0.3.x 版本完全支持通过
QueryRunner.query()方法执行原生SQL,MigrationInterface仅暴露QueryRunner参数是版本迭代后的正常设计,原生SQL执行能力没有被移除。 - 该报错和Mac系统环境没有关联,根因是传入的SQL语句不符合PostgreSQL的标准语法规则。0.2.x版本能正常运行是因为旧版本底层对部分非标准写法做了隐式语法转换,0.3.x版本移除了这类额外的兼容处理,会将传入的SQL原封不动发送给数据库驱动执行,不符合语法的语句会直接由数据库抛出错误。
问题根因
你写的条件删表语句语法顺序错误。PostgreSQL标准的条件删表语法格式为:
DROP TABLE IF EXISTS <表名> [其他选项]
代码中将IF EXISTS写在了DROP TABLE关键字之前,数据库解析SQL时第一个遇到的关键字是IF,不符合语句起始的语法规则,因此抛出syntax error at or near "IF"错误。
可行修复方案
- 修正所有顺序错误的删表语句,调整为符合PostgreSQL标准的写法:
错误写法示例:
修正后写法:IF EXISTS DROP TABLE "onetime_viewer_token" CASCADE IF EXISTS DROP TABLE "onetime_transfer_token"DROP TABLE IF EXISTS "onetime_viewer_token" CASCADE DROP TABLE IF EXISTS "onetime_transfer_token" - 全面检查迁移脚本中所有自定义原生SQL,对照当前使用的数据库官方语法规则校验正确性。0.3.x版本不再做隐式语法兼容,所有传入
queryRunner.query()的语句必须完全符合数据库本身的语法要求。 - 针对PostgreSQL不支持直接加
IF EXISTS的操作(比如删除约束、删除自定义类型等),可以通过PL/pgSQL的DO块包裹条件判断逻辑后传入执行,示例:// 判断外键存在时再删除,避免重复执行迁移报错 await queryRunner.query(` DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'FK_cc3204010e82bba2a8cdafb30fc' ) THEN ALTER TABLE "discord_role" DROP CONSTRAINT "FK_cc3204010e82bba2a8cdafb30fc"; END IF; END $$; `)
内容的提问来源于stack exchange,提问作者Igor Shmukler
相关产品推荐
相关产品推荐

