-- ============================================================ -- Checkpoint 9: 表结构创建综合验证脚本 -- Feature: database-migration, Property 1: 表结构完整性 -- Validates: All Requirements from Tasks 2-8 -- ============================================================ SET NOCOUNT ON; PRINT '========================================'; PRINT 'Checkpoint 9: 表结构创建综合验证报告'; PRINT '执行时间: ' + CONVERT(VARCHAR, GETDATE(), 120); PRINT '========================================'; PRINT ''; -- ============================================================ -- 1. 验证所有预期表是否存在 -- ============================================================ PRINT '1. 验证所有预期表是否存在'; PRINT '========================================'; DECLARE @expected_tables TABLE ( category NVARCHAR(50), table_name NVARCHAR(50), source_table NVARCHAR(50), expected_records INT ); -- 用户系统表 (Task 2) INSERT INTO @expected_tables VALUES ('用户系统', 'users', 'user', 2202); INSERT INTO @expected_tables VALUES ('用户系统', 'user_accounts', 'user_account', 3452); INSERT INTO @expected_tables VALUES ('用户系统', 'user_login_logs', 'user_login_log', 11584); INSERT INTO @expected_tables VALUES ('用户系统', 'user_addresses', 'user_address', 51); -- 商品系统表 (Task 3) INSERT INTO @expected_tables VALUES ('商品系统', 'goods', 'goods', 503); INSERT INTO @expected_tables VALUES ('商品系统', 'goods_items', 'goods_list', 1852); INSERT INTO @expected_tables VALUES ('商品系统', 'goods_types', 'goods_type', 13); INSERT INTO @expected_tables VALUES ('商品系统', 'goods_extensions', 'goods_extend', 34); INSERT INTO @expected_tables VALUES ('商品系统', 'prize_levels', 'shang', 106); -- 订单系统表 (Task 4) INSERT INTO @expected_tables VALUES ('订单系统', 'orders', 'order', 15); INSERT INTO @expected_tables VALUES ('订单系统', 'order_items', 'order_list', 67); INSERT INTO @expected_tables VALUES ('订单系统', 'order_items_recovery', 'order_list_recovery', 8); INSERT INTO @expected_tables VALUES ('订单系统', 'order_items_send', 'order_list_send', 0); -- 财务系统表 (Task 5) INSERT INTO @expected_tables VALUES ('财务系统', 'profit_money', 'profit_money', 25770); INSERT INTO @expected_tables VALUES ('财务系统', 'profit_integral', 'profit_integral', 33187); INSERT INTO @expected_tables VALUES ('财务系统', 'profit_money2', 'profit_money2', 19277); INSERT INTO @expected_tables VALUES ('财务系统', 'profit_pay', 'profit_pay', 3211); INSERT INTO @expected_tables VALUES ('财务系统', 'profit_score', 'profit_score', 0); INSERT INTO @expected_tables VALUES ('财务系统', 'profit_ou_qi', 'profit_ou_qi', 8339); -- 优惠券系统表 (Task 6) INSERT INTO @expected_tables VALUES ('优惠券系统', 'coupons', 'coupon', 19); INSERT INTO @expected_tables VALUES ('优惠券系统', 'coupon_receives', 'coupon_receive', 7799); INSERT INTO @expected_tables VALUES ('优惠券系统', 'user_coupons', 'user_coupon', 0); -- 钻石系统表 (Task 6) INSERT INTO @expected_tables VALUES ('钻石系统', 'diamond_products', 'diamond_products', 5); INSERT INTO @expected_tables VALUES ('钻石系统', 'diamond_orders', 'diamond_orders', 398); -- 任务签到系统表 (Task 7) INSERT INTO @expected_tables VALUES ('任务签到', 'tasks', 'task_list', 9); INSERT INTO @expected_tables VALUES ('任务签到', 'user_tasks', 'user_task_list', 4899); INSERT INTO @expected_tables VALUES ('任务签到', 'sign_configs', 'sign_config', 35); INSERT INTO @expected_tables VALUES ('任务签到', 'user_signs', 'user_sign', 702); -- VIP系统表 (Task 7) INSERT INTO @expected_tables VALUES ('VIP系统', 'vip_levels', 'quan_yi_level', 75); INSERT INTO @expected_tables VALUES ('VIP系统', 'vip_level_rewards', 'quan_yi_level_jiang', 225); INSERT INTO @expected_tables VALUES ('VIP系统', 'user_vip_rewards', 'user_quan_yi_level_jiang', 1393); -- 系统配置表 (Task 8) INSERT INTO @expected_tables VALUES ('系统配置', 'configs', 'config', 25); INSERT INTO @expected_tables VALUES ('系统配置', 'deliveries', 'delivery', 11); INSERT INTO @expected_tables VALUES ('系统配置', 'pictures', 'picture', 1176); INSERT INTO @expected_tables VALUES ('系统配置', 'adverts', 'advert', 16); -- 管理后台表 (Task 8) INSERT INTO @expected_tables VALUES ('管理后台', 'admins', 'admin', 3); INSERT INTO @expected_tables VALUES ('管理后台', 'admin_login_logs', 'admin_login_log', 0); INSERT INTO @expected_tables VALUES ('管理后台', 'admin_operation_logs', 'admin_operation_log', 0); -- 验证表存在性 SELECT e.category AS [类别], e.table_name AS [目标表名], e.source_table AS [源表名], CASE WHEN t.TABLE_NAME IS NOT NULL THEN '✓ 存在' ELSE '✗ 不存在' END AS [状态] FROM @expected_tables e LEFT JOIN INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = e.table_name AND t.TABLE_TYPE = 'BASE TABLE' ORDER BY e.category, e.table_name; -- 统计表存在情况 DECLARE @total_expected INT; DECLARE @total_exists INT; SELECT @total_expected = COUNT(*) FROM @expected_tables; SELECT @total_exists = COUNT(*) FROM @expected_tables e INNER JOIN INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = e.table_name AND t.TABLE_TYPE = 'BASE TABLE'; PRINT ''; PRINT '表存在性统计: ' + CAST(@total_exists AS VARCHAR) + '/' + CAST(@total_expected AS VARCHAR) + ' 表已创建'; PRINT ''; -- ============================================================ -- 2. 验证主键约束 -- ============================================================ PRINT '2. 验证主键约束'; PRINT '========================================'; SELECT e.category AS [类别], e.table_name AS [表名], ISNULL(tc.CONSTRAINT_NAME, '✗ 无主键') AS [主键约束], CASE WHEN tc.CONSTRAINT_NAME IS NOT NULL THEN '✓ 通过' ELSE '✗ 失败' END AS [状态] FROM @expected_tables e LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON tc.TABLE_NAME = e.table_name AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY e.category, e.table_name; -- 统计主键情况 DECLARE @pk_count INT; SELECT @pk_count = COUNT(DISTINCT e.table_name) FROM @expected_tables e INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON tc.TABLE_NAME = e.table_name AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'; PRINT ''; PRINT '主键约束统计: ' + CAST(@pk_count AS VARCHAR) + '/' + CAST(@total_expected AS VARCHAR) + ' 表有主键'; PRINT ''; -- ============================================================ -- 3. 验证索引数量 -- ============================================================ PRINT '3. 验证索引数量'; PRINT '========================================'; SELECT e.category AS [类别], e.table_name AS [表名], COUNT(i.name) AS [索引数量] FROM @expected_tables e LEFT JOIN sys.tables t ON t.name = e.table_name LEFT JOIN sys.indexes i ON i.object_id = t.object_id AND i.name IS NOT NULL GROUP BY e.category, e.table_name ORDER BY e.category, e.table_name; PRINT ''; -- ============================================================ -- 4. 验证表注释 -- ============================================================ PRINT '4. 验证表注释'; PRINT '========================================'; SELECT e.category AS [类别], e.table_name AS [表名], CAST(ep.value AS NVARCHAR(100)) AS [表注释], CASE WHEN ep.value IS NOT NULL THEN '✓ 有注释' ELSE '✗ 无注释' END AS [状态] FROM @expected_tables e LEFT JOIN sys.tables t ON t.name = e.table_name LEFT JOIN sys.extended_properties ep ON ep.major_id = t.object_id AND ep.minor_id = 0 AND ep.name = 'MS_Description' ORDER BY e.category, e.table_name; -- 统计表注释情况 DECLARE @comment_count INT; SELECT @comment_count = COUNT(*) FROM @expected_tables e INNER JOIN sys.tables t ON t.name = e.table_name INNER JOIN sys.extended_properties ep ON ep.major_id = t.object_id AND ep.minor_id = 0 AND ep.name = 'MS_Description'; PRINT ''; PRINT '表注释统计: ' + CAST(@comment_count AS VARCHAR) + '/' + CAST(@total_expected AS VARCHAR) + ' 表有注释'; PRINT ''; -- ============================================================ -- 5. 验证字段数量 -- ============================================================ PRINT '5. 验证字段数量'; PRINT '========================================'; SELECT e.category AS [类别], e.table_name AS [表名], COUNT(c.COLUMN_NAME) AS [字段数量] FROM @expected_tables e LEFT JOIN INFORMATION_SCHEMA.COLUMNS c ON c.TABLE_NAME = e.table_name GROUP BY e.category, e.table_name ORDER BY e.category, e.table_name; PRINT ''; -- ============================================================ -- 6. 验证唯一约束 -- ============================================================ PRINT '6. 验证唯一约束'; PRINT '========================================'; SELECT t.name AS [表名], i.name AS [唯一约束名], c.name AS [约束列] FROM sys.tables t INNER JOIN sys.indexes i ON t.object_id = i.object_id AND i.is_unique = 1 AND i.is_primary_key = 0 INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE t.name IN (SELECT table_name FROM @expected_tables) ORDER BY t.name, i.name; PRINT ''; -- ============================================================ -- 7. 验证无外键约束 (Requirements 12.3) -- ============================================================ PRINT '7. 验证无外键约束 (Requirements 12.3)'; PRINT '========================================'; DECLARE @fk_count INT; SELECT @fk_count = COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc WHERE tc.TABLE_NAME IN (SELECT table_name FROM @expected_tables) AND tc.CONSTRAINT_TYPE = 'FOREIGN KEY'; IF @fk_count = 0 PRINT '✓ 通过: 所有表均无外键约束'; ELSE PRINT '✗ 失败: 发现 ' + CAST(@fk_count AS VARCHAR) + ' 个外键约束'; PRINT ''; -- ============================================================ -- 8. 验证总结 -- ============================================================ PRINT '========================================'; PRINT '验证总结'; PRINT '========================================'; PRINT ''; -- 计算各项统计 DECLARE @missing_tables INT = @total_expected - @total_exists; DECLARE @missing_pk INT = @total_expected - @pk_count; DECLARE @missing_comments INT = @total_expected - @comment_count; -- 输出总结 IF @missing_tables = 0 PRINT '✓ 表结构: 所有 ' + CAST(@total_expected AS VARCHAR) + ' 个表已创建'; ELSE PRINT '✗ 表结构: 缺少 ' + CAST(@missing_tables AS VARCHAR) + ' 个表'; IF @missing_pk = 0 PRINT '✓ 主键约束: 所有表都有主键'; ELSE PRINT '⚠ 主键约束: ' + CAST(@missing_pk AS VARCHAR) + ' 个表缺少主键'; IF @fk_count = 0 PRINT '✓ 外键约束: 符合要求,无外键'; ELSE PRINT '✗ 外键约束: 不符合要求,存在外键'; IF @missing_comments = 0 PRINT '✓ 表注释: 所有表都有注释'; ELSE PRINT '⚠ 表注释: ' + CAST(@missing_comments AS VARCHAR) + ' 个表缺少注释'; PRINT ''; -- 最终结果 IF @missing_tables = 0 AND @missing_pk = 0 AND @fk_count = 0 BEGIN PRINT '========================================'; PRINT '✓ Checkpoint 9 验证通过!'; PRINT '所有表结构创建正确,可以继续数据迁移。'; PRINT '========================================'; END ELSE BEGIN PRINT '========================================'; PRINT '✗ Checkpoint 9 验证失败!'; PRINT '请检查上述问题后重新验证。'; PRINT '========================================'; END PRINT ''; PRINT '验证完成时间: ' + CONVERT(VARCHAR, GETDATE(), 120);