-- ===================================================================================== -- 商城系统数据库状态检查脚本 -- 分析现有数据库结构,生成个性化ALTER建议 -- ===================================================================================== -- ===================================================================================== -- 1. 检查现有表结构 -- ===================================================================================== -- 检查 ak_users 表字段情况 DO $$ DECLARE missing_fields TEXT[] := ARRAY[]::TEXT[]; existing_fields TEXT[] := ARRAY[]::TEXT[]; field_name TEXT; field_names TEXT[] := ARRAY['mall_status', 'mall_type', 'last_login_ip', 'total_orders', 'total_spent', 'user_level', 'points', 'verified_status']; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '检查 ak_users 表字段状态'; RAISE NOTICE '======================================================='; FOREACH field_name IN ARRAY field_names LOOP IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ak_users' AND column_name = field_name) THEN existing_fields := array_append(existing_fields, field_name); RAISE NOTICE '✓ 字段已存在: %', field_name; ELSE missing_fields := array_append(missing_fields, field_name); RAISE NOTICE '✗ 字段缺失: %', field_name; END IF; END LOOP; RAISE NOTICE '-------------------------------------------------------'; RAISE NOTICE '已存在字段数量: %', array_length(existing_fields, 1); RAISE NOTICE '缺失字段数量: %', array_length(missing_fields, 1); IF array_length(missing_fields, 1) > 0 THEN RAISE NOTICE '需要添加的字段: %', array_to_string(missing_fields, ', '); ELSE RAISE NOTICE 'ak_users 表所有商城字段均已存在'; END IF; END $$; -- 检查商城表存在情况 DO $$ DECLARE table_name TEXT; table_names TEXT[] := ARRAY['ml_user_profiles', 'ml_user_addresses', 'ml_categories', 'ml_brands', 'ml_products', 'ml_product_skus', 'ml_shops', 'ml_orders', 'ml_shopping_cart']; existing_tables TEXT[] := ARRAY[]::TEXT[]; missing_tables TEXT[] := ARRAY[]::TEXT[]; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '检查商城核心表存在情况'; RAISE NOTICE '======================================================='; FOREACH table_name IN ARRAY table_names LOOP IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = table_name) THEN existing_tables := array_append(existing_tables, table_name); RAISE NOTICE '✓ 表已存在: %', table_name; ELSE missing_tables := array_append(missing_tables, table_name); RAISE NOTICE '✗ 表缺失: %', table_name; END IF; END LOOP; RAISE NOTICE '-------------------------------------------------------'; RAISE NOTICE '已存在表数量: %', array_length(existing_tables, 1); RAISE NOTICE '缺失表数量: %', array_length(missing_tables, 1); IF array_length(missing_tables, 1) > 0 THEN RAISE NOTICE '需要创建的表: %', array_to_string(missing_tables, ', '); ELSE RAISE NOTICE '所有商城核心表均已存在'; END IF; END $$; -- ===================================================================================== -- 2. 检查现有索引情况 -- ===================================================================================== -- 检查重要索引存在情况 DO $$ DECLARE index_info RECORD; missing_indexes TEXT[] := ARRAY[]::TEXT[]; existing_indexes TEXT[] := ARRAY[]::TEXT[]; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '检查重要索引存在情况'; RAISE NOTICE '======================================================='; -- 定义重要索引列表 FOR index_info IN SELECT * FROM (VALUES ('idx_ak_users_mall_status', 'ak_users', 'mall_status'), ('idx_ak_users_mall_type', 'ak_users', 'mall_type'), ('idx_ak_users_total_orders', 'ak_users', 'total_orders'), ('idx_ml_products_cid', 'ml_products', 'cid'), ('idx_ml_products_slug', 'ml_products', 'slug'), ('idx_ml_categories_cid', 'ml_categories', 'cid'), ('idx_ml_orders_cid', 'ml_orders', 'cid'), ('idx_ml_shops_cid', 'ml_shops', 'cid') ) AS t(index_name, table_name, column_name) LOOP -- 检查表是否存在 IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = index_info.table_name) THEN -- 检查索引是否存在 IF EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = index_info.index_name) THEN existing_indexes := array_append(existing_indexes, index_info.index_name); RAISE NOTICE '✓ 索引已存在: % (表: %)', index_info.index_name, index_info.table_name; ELSE missing_indexes := array_append(missing_indexes, index_info.index_name); RAISE NOTICE '✗ 索引缺失: % (表: %)', index_info.index_name, index_info.table_name; END IF; ELSE RAISE NOTICE '○ 表不存在,跳过索引检查: % (表: %)', index_info.index_name, index_info.table_name; END IF; END LOOP; RAISE NOTICE '-------------------------------------------------------'; RAISE NOTICE '已存在索引数量: %', array_length(existing_indexes, 1); RAISE NOTICE '缺失索引数量: %', array_length(missing_indexes, 1); END $$; -- ===================================================================================== -- 3. 检查扩展和函数 -- ===================================================================================== -- 检查必要的PostgreSQL扩展 DO $$ DECLARE ext_name TEXT; extensions TEXT[] := ARRAY['uuid-ossp', 'btree_gin']; existing_ext TEXT[] := ARRAY[]::TEXT[]; missing_ext TEXT[] := ARRAY[]::TEXT[]; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '检查PostgreSQL扩展'; RAISE NOTICE '======================================================='; FOREACH ext_name IN ARRAY extensions LOOP IF EXISTS (SELECT 1 FROM pg_extension WHERE extname = ext_name) THEN existing_ext := array_append(existing_ext, ext_name); RAISE NOTICE '✓ 扩展已安装: %', ext_name; ELSE missing_ext := array_append(missing_ext, ext_name); RAISE NOTICE '✗ 扩展缺失: %', ext_name; END IF; END LOOP; IF array_length(missing_ext, 1) > 0 THEN RAISE NOTICE '需要安装的扩展: %', array_to_string(missing_ext, ', '); END IF; END $$; -- 检查商城相关函数 DO $$ DECLARE func_name TEXT; functions TEXT[] := ARRAY['generate_order_no', 'calculate_cart_total', 'update_user_mall_stats']; existing_funcs TEXT[] := ARRAY[]::TEXT[]; missing_funcs TEXT[] := ARRAY[]::TEXT[]; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '检查商城相关函数'; RAISE NOTICE '======================================================='; FOREACH func_name IN ARRAY functions LOOP IF EXISTS (SELECT 1 FROM pg_proc WHERE proname = func_name) THEN existing_funcs := array_append(existing_funcs, func_name); RAISE NOTICE '✓ 函数已存在: %', func_name; ELSE missing_funcs := array_append(missing_funcs, func_name); RAISE NOTICE '✗ 函数缺失: %', func_name; END IF; END LOOP; IF array_length(missing_funcs, 1) > 0 THEN RAISE NOTICE '需要创建的函数: %', array_to_string(missing_funcs, ', '); END IF; END $$; -- ===================================================================================== -- 4. 生成个性化建议 -- ===================================================================================== DO $$ DECLARE ak_users_missing INTEGER := 0; mall_tables_missing INTEGER := 0; suggestion TEXT := ''; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '个性化升级建议'; RAISE NOTICE '======================================================='; -- 统计ak_users缺失字段 SELECT COUNT(*) INTO ak_users_missing FROM (VALUES ('mall_status'), ('mall_type'), ('total_orders'), ('total_spent')) AS t(field) WHERE NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = 'ak_users' AND column_name = t.field ); -- 统计商城表缺失情况 SELECT COUNT(*) INTO mall_tables_missing FROM (VALUES ('ml_products'), ('ml_categories'), ('ml_orders'), ('ml_shops')) AS t(table_name) WHERE NOT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_name = t.table_name ); -- 生成建议 IF ak_users_missing > 0 AND mall_tables_missing > 0 THEN suggestion := '建议使用 mall_alter_upgrade.sql(完整升级脚本)'; ELSIF ak_users_missing > 0 AND mall_tables_missing = 0 THEN suggestion := '建议使用 mall_fields_only_upgrade.sql(仅字段升级脚本)'; ELSIF ak_users_missing = 0 AND mall_tables_missing > 0 THEN suggestion := '建议使用 mall_migration.sql(表结构创建脚本)'; ELSE suggestion := '数据库结构已完整,建议检查数据完整性和权限配置'; END IF; RAISE NOTICE '根据您的数据库状态分析:'; RAISE NOTICE '• ak_users 表缺失字段数: %', ak_users_missing; RAISE NOTICE '• 缺失商城核心表数: %', mall_tables_missing; RAISE NOTICE ''; RAISE NOTICE '推荐执行方案: %', suggestion; -- 详细建议 RAISE NOTICE ''; RAISE NOTICE '详细执行步骤:'; IF ak_users_missing > 0 THEN RAISE NOTICE '1. 先执行字段升级脚本为ak_users表添加商城字段'; END IF; IF mall_tables_missing > 0 THEN RAISE NOTICE '2. 执行表结构创建脚本建立商城核心表'; END IF; RAISE NOTICE '3. 执行SEO和安全策略脚本(mall_seo_security.sql)'; RAISE NOTICE '4. 根据需要执行模拟数据插入脚本进行测试'; END $$; -- ===================================================================================== -- 5. 生成具体的ALTER语句(可选) -- ===================================================================================== -- 生成ak_users表缺失字段的ALTER语句 DO $$ DECLARE alter_statements TEXT := ''; field_name TEXT; field_configs TEXT[] := ARRAY[ 'mall_status INTEGER DEFAULT 1 CHECK (mall_status IN (1,2))', 'mall_type INTEGER DEFAULT 1 CHECK (mall_type IN (1,2,3))', 'total_orders INTEGER DEFAULT 0 CHECK (total_orders >= 0)', 'total_spent DECIMAL(12,2) DEFAULT 0.00 CHECK (total_spent >= 0)', 'user_level INTEGER DEFAULT 1 CHECK (user_level >= 1 AND user_level <= 10)', 'points INTEGER DEFAULT 0 CHECK (points >= 0)', 'verified_status INTEGER DEFAULT 0 CHECK (verified_status IN (0,1,2))' ]; field_names TEXT[] := ARRAY['mall_status', 'mall_type', 'total_orders', 'total_spent', 'user_level', 'points', 'verified_status']; i INTEGER; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '生成ak_users表ALTER语句'; RAISE NOTICE '======================================================='; FOR i IN 1..array_length(field_names, 1) LOOP field_name := field_names[i]; IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ak_users' AND column_name = field_name) THEN alter_statements := alter_statements || format('ALTER TABLE public.ak_users ADD COLUMN %s;' || chr(10), field_configs[i]); RAISE NOTICE '需要执行: ALTER TABLE public.ak_users ADD COLUMN %;', field_configs[i]; END IF; END LOOP; IF alter_statements = '' THEN RAISE NOTICE 'ak_users表无需添加字段'; ELSE RAISE NOTICE ''; RAISE NOTICE '完整ALTER脚本:'; RAISE NOTICE '%', alter_statements; END IF; END $$; -- ===================================================================================== -- 6. 数据完整性检查 -- ===================================================================================== DO $$ DECLARE users_count INTEGER; profiles_count INTEGER; BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '数据完整性检查'; RAISE NOTICE '======================================================='; -- 检查用户表数据 SELECT COUNT(*) INTO users_count FROM public.ak_users; RAISE NOTICE 'ak_users 表用户数量: %', users_count; -- 检查用户档案表(如果存在) IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'ml_user_profiles') THEN SELECT COUNT(*) INTO profiles_count FROM public.ml_user_profiles; RAISE NOTICE 'ml_user_profiles 表档案数量: %', profiles_count; IF users_count > profiles_count THEN RAISE NOTICE '注意: 有 % 个用户缺少商城档案,建议执行档案补充脚本', users_count - profiles_count; END IF; ELSE RAISE NOTICE 'ml_user_profiles 表不存在'; END IF; END $$; -- ===================================================================================== -- 完成提示 -- ===================================================================================== DO $$ BEGIN RAISE NOTICE '======================================================='; RAISE NOTICE '数据库状态检查完成!'; RAISE NOTICE '======================================================='; RAISE NOTICE '请根据上述分析结果选择合适的升级脚本:'; RAISE NOTICE ''; RAISE NOTICE '• mall_alter_upgrade.sql - 完整升级(表+字段+索引+函数)'; RAISE NOTICE '• mall_fields_only_upgrade.sql - 仅字段升级(最小化修改)'; RAISE NOTICE '• mall_migration.sql - 完整建表(全新部署)'; RAISE NOTICE '• mall_seo_security.sql - SEO优化和安全策略'; RAISE NOTICE ''; RAISE NOTICE '建议在生产环境执行前先在测试环境验证!'; RAISE NOTICE '======================================================='; END $$;