-- ========================================================= -- 测试管理模块数据库初始化脚本(_time 字段版本) -- 适用数据库:PostgreSQL -- 说明: -- 1. 本脚本与当前后端代码字段保持一致 -- 2. 所有时间字段统一使用 *_time 后缀 -- 3. 主表包含 is_delete 逻辑删除字段 -- ========================================================= -- ========================================================= -- 一、项目相关 -- ========================================================= -- ------------------------- -- 1. 项目表 -- ------------------------- CREATE TABLE IF NOT EXISTS project ( id BIGSERIAL PRIMARY KEY, key VARCHAR(32) UNIQUE NOT NULL, name VARCHAR(128) NOT NULL, description TEXT, department VARCHAR(64), status SMALLINT DEFAULT 1, config JSONB DEFAULT '{}'::jsonb, created_by BIGINT, is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE project IS '项目表'; COMMENT ON COLUMN project.id IS '主键ID'; COMMENT ON COLUMN project.key IS '项目唯一标识,如 XP2024'; COMMENT ON COLUMN project.name IS '项目名称'; COMMENT ON COLUMN project.description IS '项目描述'; COMMENT ON COLUMN project.department IS '所属部门'; COMMENT ON COLUMN project.status IS '项目状态:1启用 0禁用'; COMMENT ON COLUMN project.config IS '扩展配置,JSON格式'; COMMENT ON COLUMN project.created_by IS '创建人'; COMMENT ON COLUMN project.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN project.created_time IS '创建时间'; COMMENT ON COLUMN project.updated_time IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_project_status ON project(status); CREATE INDEX IF NOT EXISTS idx_project_is_delete ON project(is_delete); -- ------------------------- -- 2. 项目成员表 -- ------------------------- CREATE TABLE IF NOT EXISTS project_member ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, user_id BIGINT NOT NULL, role SMALLINT NOT NULL, joined_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE project_member IS '项目成员表'; COMMENT ON COLUMN project_member.id IS '主键ID'; COMMENT ON COLUMN project_member.project_id IS '项目ID'; COMMENT ON COLUMN project_member.user_id IS '用户ID'; COMMENT ON COLUMN project_member.role IS '角色:1测试经理 2测试工程师 3开发工程师 4访客'; COMMENT ON COLUMN project_member.joined_time IS '加入时间'; CREATE UNIQUE INDEX IF NOT EXISTS uk_project_member ON project_member(project_id, user_id); CREATE INDEX IF NOT EXISTS idx_member_user ON project_member(user_id); CREATE INDEX IF NOT EXISTS idx_member_project_id ON project_member(project_id); -- ------------------------- -- 3. 环境配置表 -- ------------------------- CREATE TABLE IF NOT EXISTS environment ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, name VARCHAR(64) NOT NULL, variables JSONB NOT NULL, is_encrypted BOOLEAN DEFAULT FALSE, is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE environment IS '环境配置表'; COMMENT ON COLUMN environment.id IS '主键ID'; COMMENT ON COLUMN environment.project_id IS '项目ID'; COMMENT ON COLUMN environment.name IS '环境名称,如 dev/test/staging/prod'; COMMENT ON COLUMN environment.variables IS '环境变量配置,JSON格式'; COMMENT ON COLUMN environment.is_encrypted IS '敏感信息是否已加密'; COMMENT ON COLUMN environment.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN environment.created_time IS '创建时间'; CREATE INDEX IF NOT EXISTS idx_environment_project_id ON environment(project_id); CREATE INDEX IF NOT EXISTS idx_environment_is_delete ON environment(is_delete); -- ------------------------- -- 4. 产品表 -- ------------------------- CREATE TABLE IF NOT EXISTS product ( id BIGSERIAL PRIMARY KEY, name VARCHAR(128) NOT NULL, code VARCHAR(64) UNIQUE NOT NULL, description TEXT, status SMALLINT DEFAULT 1, is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE product IS '产品表'; COMMENT ON COLUMN product.id IS '主键ID'; COMMENT ON COLUMN product.name IS '产品名称'; COMMENT ON COLUMN product.code IS '产品编码'; COMMENT ON COLUMN product.description IS '产品描述'; COMMENT ON COLUMN product.status IS '产品状态:1启用 0禁用'; COMMENT ON COLUMN product.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN product.created_time IS '创建时间'; COMMENT ON COLUMN product.updated_time IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_product_status ON product(status); CREATE INDEX IF NOT EXISTS idx_product_is_delete ON product(is_delete); -- ========================================================= -- 二、用例相关 -- ========================================================= -- ------------------------- -- 4. 模块表 -- ------------------------- CREATE TABLE IF NOT EXISTS module ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, parent_id BIGINT DEFAULT 0, name VARCHAR(128) NOT NULL, sort_order INTEGER DEFAULT 0, path VARCHAR(512), is_delete INTEGER DEFAULT 0 ); COMMENT ON TABLE module IS '模块树表,支持多层级模块结构'; COMMENT ON COLUMN module.id IS '主键ID'; COMMENT ON COLUMN module.project_id IS '项目ID'; COMMENT ON COLUMN module.parent_id IS '父模块ID,0表示根节点'; COMMENT ON COLUMN module.name IS '模块名称'; COMMENT ON COLUMN module.sort_order IS '排序值'; COMMENT ON COLUMN module.path IS '模块路径,如 /1/23/45'; COMMENT ON COLUMN module.is_delete IS '逻辑删除标记:0未删除 1已删除'; CREATE INDEX IF NOT EXISTS idx_module_project ON module(project_id); CREATE INDEX IF NOT EXISTS idx_module_parent_id ON module(parent_id); CREATE INDEX IF NOT EXISTS idx_module_is_delete ON module(is_delete); -- ------------------------- -- 5. 用例表 -- ------------------------- CREATE TABLE IF NOT EXISTS test_case ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, module_id BIGINT REFERENCES module(id) ON DELETE SET NULL, case_key VARCHAR(64) NOT NULL, title VARCHAR(255) NOT NULL, preconditions TEXT, steps JSONB NOT NULL DEFAULT '[]'::jsonb, priority SMALLINT DEFAULT 2, case_type SMALLINT DEFAULT 1, tags VARCHAR(64)[] DEFAULT '{}'::varchar[], status SMALLINT DEFAULT 1, created_by BIGINT, is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE test_case IS '测试用例表'; COMMENT ON COLUMN test_case.id IS '主键ID'; COMMENT ON COLUMN test_case.project_id IS '项目ID'; COMMENT ON COLUMN test_case.module_id IS '所属模块ID'; COMMENT ON COLUMN test_case.case_key IS '项目内唯一编号,如 TC-001'; COMMENT ON COLUMN test_case.title IS '用例标题'; COMMENT ON COLUMN test_case.preconditions IS '前置条件'; COMMENT ON COLUMN test_case.steps IS '测试步骤,JSON数组'; COMMENT ON COLUMN test_case.priority IS '优先级:0P0 1P1 2P2 3P3'; COMMENT ON COLUMN test_case.case_type IS '用例类型:1功能 2性能 3安全 4接口'; COMMENT ON COLUMN test_case.tags IS '标签数组'; COMMENT ON COLUMN test_case.status IS '状态:1正常 2已废弃 3评审中'; COMMENT ON COLUMN test_case.created_by IS '创建人'; COMMENT ON COLUMN test_case.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN test_case.created_time IS '创建时间'; COMMENT ON COLUMN test_case.updated_time IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_case_project ON test_case(project_id); CREATE INDEX IF NOT EXISTS idx_case_module ON test_case(module_id); CREATE INDEX IF NOT EXISTS idx_case_priority ON test_case(priority); CREATE INDEX IF NOT EXISTS idx_case_status ON test_case(status); CREATE INDEX IF NOT EXISTS idx_case_is_delete ON test_case(is_delete); CREATE UNIQUE INDEX IF NOT EXISTS uk_test_case_project_case_key ON test_case(project_id, case_key); -- ------------------------- -- 6. 用例快照表 -- ------------------------- CREATE TABLE IF NOT EXISTS case_snapshot ( id BIGSERIAL PRIMARY KEY, case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE, version INTEGER NOT NULL, snapshot JSONB NOT NULL, created_by BIGINT, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE case_snapshot IS '用例版本快照表'; COMMENT ON COLUMN case_snapshot.id IS '主键ID'; COMMENT ON COLUMN case_snapshot.case_id IS '用例ID'; COMMENT ON COLUMN case_snapshot.version IS '版本号'; COMMENT ON COLUMN case_snapshot.snapshot IS '完整快照内容'; COMMENT ON COLUMN case_snapshot.created_by IS '创建人'; COMMENT ON COLUMN case_snapshot.created_time IS '创建时间'; CREATE INDEX IF NOT EXISTS idx_case_snapshot_case_id ON case_snapshot(case_id); CREATE UNIQUE INDEX IF NOT EXISTS uk_case_snapshot_case_version ON case_snapshot(case_id, version); -- ------------------------- -- 7. 用例评审表 -- ------------------------- CREATE TABLE IF NOT EXISTS case_review ( id BIGSERIAL PRIMARY KEY, case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE, reviewer_id BIGINT NOT NULL, status SMALLINT DEFAULT 0, comments TEXT, diff_content TEXT, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, reviewed_time TIMESTAMP ); COMMENT ON TABLE case_review IS '用例评审表'; COMMENT ON COLUMN case_review.id IS '主键ID'; COMMENT ON COLUMN case_review.case_id IS '用例ID'; COMMENT ON COLUMN case_review.reviewer_id IS '评审人ID'; COMMENT ON COLUMN case_review.status IS '评审状态:0待评审 1通过 2驳回 3建议修改'; COMMENT ON COLUMN case_review.comments IS '评审意见'; COMMENT ON COLUMN case_review.diff_content IS '变更差异内容,通常为JSON diff字符串'; COMMENT ON COLUMN case_review.created_time IS '创建时间'; COMMENT ON COLUMN case_review.reviewed_time IS '评审时间'; CREATE INDEX IF NOT EXISTS idx_case_review_case_id ON case_review(case_id); CREATE INDEX IF NOT EXISTS idx_case_review_reviewer_id ON case_review(reviewer_id); -- ========================================================= -- 三、测试计划相关 -- ========================================================= -- ------------------------- -- 8. 测试计划表 -- ------------------------- CREATE TABLE IF NOT EXISTS test_plan ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, name VARCHAR(128) NOT NULL, version VARCHAR(32), description TEXT, start_date DATE, end_date DATE, owner_id BIGINT, status SMALLINT DEFAULT 0, environment_id BIGINT REFERENCES environment(id), is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE test_plan IS '测试计划表'; COMMENT ON COLUMN test_plan.id IS '主键ID'; COMMENT ON COLUMN test_plan.project_id IS '项目ID'; COMMENT ON COLUMN test_plan.name IS '计划名称'; COMMENT ON COLUMN test_plan.version IS '测试版本号'; COMMENT ON COLUMN test_plan.description IS '计划描述'; COMMENT ON COLUMN test_plan.start_date IS '开始日期'; COMMENT ON COLUMN test_plan.end_date IS '结束日期'; COMMENT ON COLUMN test_plan.owner_id IS '负责人ID'; COMMENT ON COLUMN test_plan.status IS '计划状态:0草稿 1进行中 2已完成 3已归档'; COMMENT ON COLUMN test_plan.environment_id IS '关联环境ID'; COMMENT ON COLUMN test_plan.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN test_plan.created_time IS '创建时间'; COMMENT ON COLUMN test_plan.updated_time IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_test_plan_project_id ON test_plan(project_id); CREATE INDEX IF NOT EXISTS idx_test_plan_status ON test_plan(status); CREATE INDEX IF NOT EXISTS idx_test_plan_is_delete ON test_plan(is_delete); -- ------------------------- -- 9. 计划用例表 -- ------------------------- CREATE TABLE IF NOT EXISTS plan_case ( id BIGSERIAL PRIMARY KEY, plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE, case_id BIGINT NOT NULL REFERENCES test_case(id), assignee_id BIGINT, round_no INTEGER DEFAULT 1, status SMALLINT DEFAULT 0, actual_result TEXT, defect_links JSONB DEFAULT '[]'::jsonb, attachments JSONB DEFAULT '[]'::jsonb, executed_time TIMESTAMP, execution_duration INTEGER ); COMMENT ON TABLE plan_case IS '计划与用例关联表,同时存储执行结果'; COMMENT ON COLUMN plan_case.id IS '主键ID'; COMMENT ON COLUMN plan_case.plan_id IS '计划ID'; COMMENT ON COLUMN plan_case.case_id IS '用例ID'; COMMENT ON COLUMN plan_case.assignee_id IS '执行人ID'; COMMENT ON COLUMN plan_case.round_no IS '执行轮次'; COMMENT ON COLUMN plan_case.status IS '执行状态:0未开始 1通过 2失败 3阻塞'; COMMENT ON COLUMN plan_case.actual_result IS '实际执行结果'; COMMENT ON COLUMN plan_case.defect_links IS '缺陷链接数组'; COMMENT ON COLUMN plan_case.attachments IS '附件数组'; COMMENT ON COLUMN plan_case.executed_time IS '执行时间'; COMMENT ON COLUMN plan_case.execution_duration IS '执行耗时,单位秒'; CREATE UNIQUE INDEX IF NOT EXISTS uk_plan_case_round ON plan_case(plan_id, case_id, round_no); CREATE INDEX IF NOT EXISTS idx_plan_case_plan ON plan_case(plan_id); CREATE INDEX IF NOT EXISTS idx_plan_case_assignee ON plan_case(assignee_id); CREATE INDEX IF NOT EXISTS idx_plan_case_status ON plan_case(status); -- ------------------------- -- 10. 测试轮次表 -- ------------------------- CREATE TABLE IF NOT EXISTS test_round ( id BIGSERIAL PRIMARY KEY, plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE, round_no INTEGER NOT NULL, name VARCHAR(64), start_date DATE, end_date DATE ); COMMENT ON TABLE test_round IS '测试轮次表'; COMMENT ON COLUMN test_round.id IS '主键ID'; COMMENT ON COLUMN test_round.plan_id IS '计划ID'; COMMENT ON COLUMN test_round.round_no IS '轮次编号'; COMMENT ON COLUMN test_round.name IS '轮次名称'; COMMENT ON COLUMN test_round.start_date IS '开始日期'; COMMENT ON COLUMN test_round.end_date IS '结束日期'; CREATE UNIQUE INDEX IF NOT EXISTS uk_test_round_plan_round_no ON test_round(plan_id, round_no); CREATE INDEX IF NOT EXISTS idx_test_round_plan_id ON test_round(plan_id); -- ========================================================= -- 四、报告相关 -- ========================================================= -- ------------------------- -- 11. 报告表 -- ------------------------- CREATE TABLE IF NOT EXISTS report ( id BIGSERIAL PRIMARY KEY, plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE, name VARCHAR(128) NOT NULL, report_type SMALLINT DEFAULT 1, summary JSONB, content TEXT, file_url VARCHAR(512), generated_by BIGINT, generated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE report IS '测试报告表'; COMMENT ON COLUMN report.id IS '主键ID'; COMMENT ON COLUMN report.plan_id IS '计划ID'; COMMENT ON COLUMN report.name IS '报告名称'; COMMENT ON COLUMN report.report_type IS '报告类型:1实时报告 2归档报告'; COMMENT ON COLUMN report.summary IS '报告统计摘要,JSON格式'; COMMENT ON COLUMN report.content IS '报告HTML内容'; COMMENT ON COLUMN report.file_url IS '导出文件地址'; COMMENT ON COLUMN report.generated_by IS '生成人'; COMMENT ON COLUMN report.generated_time IS '生成时间'; CREATE INDEX IF NOT EXISTS idx_report_plan_id ON report(plan_id); CREATE INDEX IF NOT EXISTS idx_report_generated_time ON report(generated_time); -- ------------------------- -- 12. 缺陷同步表 -- ------------------------- CREATE TABLE IF NOT EXISTS defect_sync ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id), external_id VARCHAR(64) NOT NULL, external_system VARCHAR(32), plan_case_id BIGINT REFERENCES plan_case(id), status VARCHAR(32), last_sync_time TIMESTAMP ); COMMENT ON TABLE defect_sync IS '缺陷同步表,用于记录外部缺陷系统关联关系'; COMMENT ON COLUMN defect_sync.id IS '主键ID'; COMMENT ON COLUMN defect_sync.project_id IS '项目ID'; COMMENT ON COLUMN defect_sync.external_id IS '外部缺陷ID,如 JIRA-123'; COMMENT ON COLUMN defect_sync.external_system IS '外部系统,如 jira/tapd/zentao'; COMMENT ON COLUMN defect_sync.plan_case_id IS '计划用例执行ID'; COMMENT ON COLUMN defect_sync.status IS '外部缺陷状态'; COMMENT ON COLUMN defect_sync.last_sync_time IS '最后同步时间'; CREATE INDEX IF NOT EXISTS idx_defect_sync_project_id ON defect_sync(project_id); CREATE INDEX IF NOT EXISTS idx_defect_sync_plan_case_id ON defect_sync(plan_case_id); CREATE INDEX IF NOT EXISTS idx_defect_sync_external_id ON defect_sync(external_id); -- ========================================================= -- 五、造数相关 -- ========================================================= -- ------------------------- -- 13. 造数器表 -- ------------------------- CREATE TABLE IF NOT EXISTS data_builder ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE, name VARCHAR(128) NOT NULL, description TEXT, builder_type SMALLINT DEFAULT 1, definition JSONB NOT NULL, input_schema JSONB, output_example JSONB, created_by BIGINT, is_delete INTEGER DEFAULT 0, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE data_builder IS '数据构造器表'; COMMENT ON COLUMN data_builder.id IS '主键ID'; COMMENT ON COLUMN data_builder.project_id IS '项目ID'; COMMENT ON COLUMN data_builder.name IS '造数器名称'; COMMENT ON COLUMN data_builder.description IS '造数器描述'; COMMENT ON COLUMN data_builder.builder_type IS '造数器类型:1流程编排 2SQL 3脚本'; COMMENT ON COLUMN data_builder.definition IS '造数逻辑定义,JSON格式'; COMMENT ON COLUMN data_builder.input_schema IS '输入参数结构定义'; COMMENT ON COLUMN data_builder.output_example IS '输出示例'; COMMENT ON COLUMN data_builder.created_by IS '创建人'; COMMENT ON COLUMN data_builder.is_delete IS '逻辑删除标记:0未删除 1已删除'; COMMENT ON COLUMN data_builder.created_time IS '创建时间'; COMMENT ON COLUMN data_builder.updated_time IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_data_builder_project_id ON data_builder(project_id); CREATE INDEX IF NOT EXISTS idx_data_builder_is_delete ON data_builder(is_delete); -- ------------------------- -- 14. 造数任务表 -- ------------------------- CREATE TABLE IF NOT EXISTS data_task ( id BIGSERIAL PRIMARY KEY, builder_id BIGINT NOT NULL REFERENCES data_builder(id), project_id BIGINT NOT NULL, params JSONB, status SMALLINT DEFAULT 0, result_data JSONB, error_message TEXT, created_by BIGINT, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_time TIMESTAMP ); COMMENT ON TABLE data_task IS '数据生成任务表'; COMMENT ON COLUMN data_task.id IS '主键ID'; COMMENT ON COLUMN data_task.builder_id IS '造数器ID'; COMMENT ON COLUMN data_task.project_id IS '项目ID'; COMMENT ON COLUMN data_task.params IS '任务入参,JSON格式'; COMMENT ON COLUMN data_task.status IS '任务状态:0等待 1执行中 2成功 3失败'; COMMENT ON COLUMN data_task.result_data IS '生成结果数据'; COMMENT ON COLUMN data_task.error_message IS '错误信息'; COMMENT ON COLUMN data_task.created_by IS '创建人'; COMMENT ON COLUMN data_task.created_time IS '创建时间'; COMMENT ON COLUMN data_task.completed_time IS '完成时间'; CREATE INDEX IF NOT EXISTS idx_task_status ON data_task(status); CREATE INDEX IF NOT EXISTS idx_data_task_builder_id ON data_task(builder_id); CREATE INDEX IF NOT EXISTS idx_data_task_project_id ON data_task(project_id); -- ========================================================= -- 六、更新时间自动维护触发器 -- 说明: -- PostgreSQL 需要借助触发器维护 updated_time -- ========================================================= CREATE OR REPLACE FUNCTION update_updated_time_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_time = CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_project_updated_time ON project; CREATE TRIGGER trg_project_updated_time BEFORE UPDATE ON project FOR EACH ROW EXECUTE FUNCTION update_updated_time_column(); DROP TRIGGER IF EXISTS trg_product_updated_time ON product; CREATE TRIGGER trg_product_updated_time BEFORE UPDATE ON product FOR EACH ROW EXECUTE FUNCTION update_updated_time_column(); DROP TRIGGER IF EXISTS trg_test_case_updated_time ON test_case; CREATE TRIGGER trg_test_case_updated_time BEFORE UPDATE ON test_case FOR EACH ROW EXECUTE FUNCTION update_updated_time_column(); DROP TRIGGER IF EXISTS trg_test_plan_updated_time ON test_plan; CREATE TRIGGER trg_test_plan_updated_time BEFORE UPDATE ON test_plan FOR EACH ROW EXECUTE FUNCTION update_updated_time_column(); DROP TRIGGER IF EXISTS trg_data_builder_updated_time ON data_builder; CREATE TRIGGER trg_data_builder_updated_time BEFORE UPDATE ON data_builder FOR EACH ROW EXECUTE FUNCTION update_updated_time_column();