-- ============================================= -- 配送效率分析 - 配送相关基础表(建表 + 升级,支持重复执行) -- 说明: -- - 本脚本用于测试阶段,为配送效率分析页面提供必要的表结构。 -- - 使用 CREATE TABLE IF NOT EXISTS + DO 块判断列/约束是否存在,实现可重复执行。 -- - 外键: -- - driver_id -> ml_delivery_drivers(id) 必须存在。 -- - user_id -> ak_users(id) 仅在 ak_users 表存在时才会创建外键(避免执行报错)。 -- ============================================= -- 1) 创建基础表(若不存在) CREATE TABLE IF NOT EXISTS public.ml_delivery_drivers ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), real_name TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS public.ml_delivery_tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ DEFAULT NOW() ); -- 2) 补齐字段(若不存在) DO $$ BEGIN -- ========================= -- ml_delivery_drivers -- ========================= IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_drivers' AND column_name='user_id' ) THEN ALTER TABLE public.ml_delivery_drivers ADD COLUMN user_id UUID; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_drivers' AND column_name='work_status' ) THEN ALTER TABLE public.ml_delivery_drivers ADD COLUMN work_status INTEGER DEFAULT 1; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_drivers' AND column_name='rating_avg' ) THEN ALTER TABLE public.ml_delivery_drivers ADD COLUMN rating_avg NUMERIC(3,2) DEFAULT 0; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_drivers' AND column_name='rating_count' ) THEN ALTER TABLE public.ml_delivery_drivers ADD COLUMN rating_count INTEGER DEFAULT 0; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_drivers' AND column_name='updated_at' ) THEN ALTER TABLE public.ml_delivery_drivers ADD COLUMN updated_at TIMESTAMPTZ DEFAULT NOW(); END IF; -- ========================= -- ml_delivery_tasks -- ========================= IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='order_id' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN order_id UUID; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='driver_id' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN driver_id UUID; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='status' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN status INTEGER DEFAULT 1; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='assigned_at' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN assigned_at TIMESTAMPTZ; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='delivered_at' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN delivered_at TIMESTAMPTZ; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='delivery_fee' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN delivery_fee NUMERIC(10,2) DEFAULT 0; END IF; IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='ml_delivery_tasks' AND column_name='updated_at' ) THEN ALTER TABLE public.ml_delivery_tasks ADD COLUMN updated_at TIMESTAMPTZ DEFAULT NOW(); END IF; END; $$; -- 3) 添加表/字段中文注释 COMMENT ON TABLE public.ml_delivery_drivers IS '配送员表'; COMMENT ON COLUMN public.ml_delivery_drivers.id IS '配送员ID'; COMMENT ON COLUMN public.ml_delivery_drivers.user_id IS '关联用户ID(可选,若存在 ak_users 表则可建立外键)'; COMMENT ON COLUMN public.ml_delivery_drivers.real_name IS '真实姓名'; COMMENT ON COLUMN public.ml_delivery_drivers.work_status IS '工作状态:1在线 2忙碌 3离线'; COMMENT ON COLUMN public.ml_delivery_drivers.rating_avg IS '平均评分(0-5)'; COMMENT ON COLUMN public.ml_delivery_drivers.rating_count IS '评分次数'; COMMENT ON COLUMN public.ml_delivery_drivers.created_at IS '创建时间'; COMMENT ON COLUMN public.ml_delivery_drivers.updated_at IS '更新时间'; COMMENT ON TABLE public.ml_delivery_tasks IS '配送任务表(接单->送达)'; COMMENT ON COLUMN public.ml_delivery_tasks.id IS '任务ID'; COMMENT ON COLUMN public.ml_delivery_tasks.order_id IS '订单ID(测试阶段可空;正式可做 UNIQUE + 外键)'; COMMENT ON COLUMN public.ml_delivery_tasks.driver_id IS '配送员ID'; COMMENT ON COLUMN public.ml_delivery_tasks.status IS '状态:1待接 2已接 3取货 4配送中 5已送达 6配送失败'; COMMENT ON COLUMN public.ml_delivery_tasks.assigned_at IS '接单时间'; COMMENT ON COLUMN public.ml_delivery_tasks.delivered_at IS '送达时间'; COMMENT ON COLUMN public.ml_delivery_tasks.delivery_fee IS '配送费'; COMMENT ON COLUMN public.ml_delivery_tasks.created_at IS '创建时间'; COMMENT ON COLUMN public.ml_delivery_tasks.updated_at IS '更新时间'; -- 4) 添加约束(幂等) DO $$ BEGIN -- drivers: real_name 唯一 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='u' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='ml_delivery_drivers_real_name_key' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT ml_delivery_drivers_real_name_key UNIQUE (real_name); END IF; -- drivers: work_status 枚举 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='chk_ml_delivery_drivers_work_status' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT chk_ml_delivery_drivers_work_status CHECK (work_status IN (1,2,3)); END IF; -- drivers: rating_avg 范围 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='chk_ml_delivery_drivers_rating_avg' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT chk_ml_delivery_drivers_rating_avg CHECK (rating_avg >= 0 AND rating_avg <= 5); END IF; -- drivers: rating_count 非负 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='chk_ml_delivery_drivers_rating_count' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT chk_ml_delivery_drivers_rating_count CHECK (rating_count >= 0); END IF; -- tasks: status 枚举 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_tasks' AND c.conname='chk_ml_delivery_tasks_status' ) THEN ALTER TABLE public.ml_delivery_tasks ADD CONSTRAINT chk_ml_delivery_tasks_status CHECK (status IN (1,2,3,4,5,6)); END IF; -- tasks: delivery_fee 非负 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_tasks' AND c.conname='chk_ml_delivery_tasks_delivery_fee' ) THEN ALTER TABLE public.ml_delivery_tasks ADD CONSTRAINT chk_ml_delivery_tasks_delivery_fee CHECK (delivery_fee >= 0); END IF; -- tasks: 时间逻辑 delivered_at >= assigned_at IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='c' AND n.nspname='public' AND t.relname='ml_delivery_tasks' AND c.conname='chk_ml_delivery_tasks_time_logic' ) THEN ALTER TABLE public.ml_delivery_tasks ADD CONSTRAINT chk_ml_delivery_tasks_time_logic CHECK ( delivered_at IS NULL OR assigned_at IS NULL OR delivered_at >= assigned_at ); END IF; -- tasks: driver_id 外键 IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='f' AND n.nspname='public' AND t.relname='ml_delivery_tasks' AND c.conname='ml_delivery_tasks_driver_id_fkey' ) THEN ALTER TABLE public.ml_delivery_tasks ADD CONSTRAINT ml_delivery_tasks_driver_id_fkey FOREIGN KEY (driver_id) REFERENCES public.ml_delivery_drivers(id) ON DELETE SET NULL; END IF; -- drivers: user_id 外键(仅当 ak_users 表存在时才创建) IF EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name='ak_users' ) THEN IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='f' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='ml_delivery_drivers_user_id_fkey' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT ml_delivery_drivers_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.ak_users(id) ON DELETE SET NULL; END IF; END IF; -- drivers: user_id 唯一(如果你不用 user_id,可以后续删除该约束) IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='u' AND n.nspname='public' AND t.relname='ml_delivery_drivers' AND c.conname='ml_delivery_drivers_user_id_key' ) THEN ALTER TABLE public.ml_delivery_drivers ADD CONSTRAINT ml_delivery_drivers_user_id_key UNIQUE (user_id); END IF; -- tasks: order_id 唯一(测试阶段允许 NULL,NULL 不冲突) IF NOT EXISTS ( SELECT 1 FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid JOIN pg_namespace n ON n.oid = t.relnamespace WHERE c.contype='u' AND n.nspname='public' AND t.relname='ml_delivery_tasks' AND c.conname='ml_delivery_tasks_order_id_key' ) THEN ALTER TABLE public.ml_delivery_tasks ADD CONSTRAINT ml_delivery_tasks_order_id_key UNIQUE (order_id); END IF; END; $$; -- 5) 索引(幂等) CREATE INDEX IF NOT EXISTS idx_ml_delivery_drivers_work_status ON public.ml_delivery_drivers(work_status); CREATE INDEX IF NOT EXISTS idx_ml_delivery_tasks_status ON public.ml_delivery_tasks(status); CREATE INDEX IF NOT EXISTS idx_ml_delivery_tasks_assigned_at ON public.ml_delivery_tasks(assigned_at); CREATE INDEX IF NOT EXISTS idx_ml_delivery_tasks_driver_id ON public.ml_delivery_tasks(driver_id); -- 完成 SELECT 'delivery tables ensured' AS message;