You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:01:34