CI中Bash处理PostgreSQL SQL文件,满足条件终止当前执行
如何在PostgreSQL迁移中终止当前SQL文件执行并跳转到下一个迁移文件?
我来帮你搞定这个需求!你想要的逻辑完全可行,咱们分两步实现:先修正SQL里的对象存在判断语法,再调整Bash循环确保只终止当前psql进程,不中断整个迁移脚本。
第一步:SQL文件内的对象存在判断与终止逻辑
PostgreSQL没有内置的TABLE_EXISTS()函数,但可以通过查询系统信息视图来检查对象是否存在。我们可以用DO块编写判断逻辑,一旦检测到对象已存在,就抛出一个自定义异常——这个异常会让psql进程非零退出,但不会终止整个Shell脚本。
检查表是否存在的示例
-- 检查public模式下的something表是否存在 DO $$ BEGIN IF EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'something' ) THEN -- 先输出提示信息,方便排查 RAISE NOTICE '表something已存在,终止当前迁移文件执行'; -- 抛出自定义异常,ERRCODE用P0001(用户定义异常) RAISE EXCEPTION '终止当前文件执行' USING ERRCODE = 'P0001'; END IF; END $$; -- 你的正常创建语句,只有上面的判断不触发时才会执行 CREATE TABLE something ( id SERIAL PRIMARY KEY, name VARCHAR(50) NOT NULL );
其他对象的判断示例
- 检查列是否存在:
DO $$ BEGIN IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'something' AND column_name = 'email' ) THEN RAISE EXCEPTION '列something.email已存在,终止当前文件执行' USING ERRCODE = 'P0001'; END IF; END $$;
- 检查索引是否存在:
DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'something' AND indexname = 'idx_something_name' ) THEN RAISE EXCEPTION '索引idx_something_name已存在,终止当前文件执行' USING ERRCODE = 'P0001'; END IF; END $$;
- 检查触发器是否存在:
DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_trigger WHERE tgname = 'trg_something_after_insert' AND tgrelid = 'public.something'::regclass ) THEN RAISE EXCEPTION '触发器trg_something_after_insert已存在,终止当前文件执行' USING ERRCODE = 'P0001'; END IF; END $$;
第二步:调整Bash循环处理逻辑
原来的循环只是简单执行每个SQL文件,现在需要添加判断:如果psql因为我们的自定义异常退出,就跳过当前文件继续下一个;如果是其他错误(比如SQL语法错误),就终止整个脚本。
调整后的Bash脚本:
# 遍历所有迁移文件 for sqlfile in "${MIGS[@]}"; do echo "开始执行迁移文件:$sqlfile" # 执行SQL文件,捕获错误输出和退出码 # -v ON_ERROR_STOP=1:让psql遇到第一个错误就停止执行当前文件 error_output=$(psql myproject_unit -v ON_ERROR_STOP=1 < "$sqlfile" 2>&1) exit_code=$? # 分情况处理退出码 if [ $exit_code -eq 0 ]; then echo "迁移文件 $sqlfile 执行成功" elif echo "$error_output" | grep -q '终止当前文件执行'; then # 匹配到我们的自定义终止消息,跳过当前文件 echo "跳过迁移文件 $sqlfile:对象已存在" continue else # 其他错误,终止整个脚本并输出错误信息 echo "迁移文件 $sqlfile 执行失败:" echo "$error_output" exit $exit_code fi done
关键说明
-v ON_ERROR_STOP=1:确保psql遇到错误就立刻停止当前文件的执行,不会继续跑后面的SQL语句。- 我们通过匹配自定义的错误消息
终止当前文件执行来区分“主动终止”和“真正的错误”,这样既跳过已执行过的迁移,又能在出现语法错误等问题时及时终止整个流程。
内容的提问来源于stack exchange,提问作者dszakal
相关产品推荐
相关产品推荐

