如何对以下SQL临时表进行数据库规范化处理?
数据库规范化处理方案
针对给定的临时表#A和#B,需按照数据库范式(核心满足第一范式1NF,同时延伸至2NF、3NF)拆分结构,最终形成3个符合规范的独立表:用户表、产品表、用户-产品关联表。
问题核心分析
- #A表:当前数据无重复,但存在冗余风险(若同一用户多次出现会重复存储信息),可作为用户基础数据的核心来源。
- #B表:
NAME字段为逗号分隔的多值内容,违反第一范式(要求列值具备原子性,不可拆分),这是需要解决的核心问题,必须拆分多值字段并建立多对多关联关系。
规范化后表结构
1. 用户表(Users)
存储唯一用户信息,确保每个用户仅存储一次:
CREATE TABLE Users ( UserID VARCHAR(5) PRIMARY KEY, -- 复用#A中的ID作为主键,新增用户需生成唯一标识 UserName VARCHAR(10) NOT NULL UNIQUE, Number INT NULL -- #B中新增用户无该字段值,允许为空 );
2. 产品表(Products)
存储唯一产品信息:
CREATE TABLE Products ( ProductID INT IDENTITY(1,1) PRIMARY KEY, -- 自增主键,也可直接用产品名作为主键 ProductName VARCHAR(10) NOT NULL UNIQUE );
3. 用户-产品关联表(UserProductRelations)
存储用户与产品的多对多关联关系,通过外键绑定两个主表:
CREATE TABLE UserProductRelations ( RelationID INT IDENTITY(1,1) PRIMARY KEY, UserID VARCHAR(5) NOT NULL FOREIGN KEY REFERENCES Users(UserID), ProductID INT NOT NULL FOREIGN KEY REFERENCES Products(ProductID), UNIQUE(UserID, ProductID) -- 避免同一用户与产品的重复关联 );
数据迁移步骤
1. 导入#A的用户数据到Users表
INSERT INTO Users(UserID, UserName, Number) SELECT ID, NAME, NUMBER FROM #A;
2. 处理#B中的新增用户(HARRY、KATTY、ALEX)
先拆分#B的多值NAME字段,提取所有唯一用户后插入Users表(示例中为新增用户生成自定义ID,也可改用自增ID):
-- 拆分#B的多值NAME字段 WITH SplitUsers AS ( SELECT TRIM(value) AS UserName FROM #B CROSS APPLY STRING_SPLIT(NAME, ',') ) -- 插入未在Users表中的新用户 INSERT INTO Users(UserName, UserID, Number) SELECT UserName, LEFT(UPPER(UserName), 1) + CAST(ROW_NUMBER() OVER(ORDER BY UserName) AS VARCHAR(4)) AS UserID, -- 示例:HARRY→H1 NULL AS Number FROM SplitUsers WHERE UserName NOT IN (SELECT UserName FROM Users);
3. 导入产品数据到Products表
INSERT INTO Products(ProductName) SELECT DISTINCT PRODUCT FROM #B;
4. 拆分#B数据并导入关联表
WITH SplitProductUsers AS ( SELECT b.PRODUCT, TRIM(s.value) AS UserName FROM #B b CROSS APPLY STRING_SPLIT(b.NAME, ',') s ) INSERT INTO UserProductRelations(UserID, ProductID) SELECT u.UserID, p.ProductID FROM SplitProductUsers spu JOIN Users u ON spu.UserName = u.UserName JOIN Products p ON spu.PRODUCT = p.ProductName;
验证查询
通过关联查询验证数据正确性,例如查询每个产品对应的用户:
SELECT p.ProductName, STRING_AGG(u.UserName, ', ') AS Users FROM Products p JOIN UserProductRelations upr ON p.ProductID = upr.ProductID JOIN Users u ON upr.UserID = u.UserID GROUP BY p.ProductName;
内容的提问来源于stack exchange,提问作者keshar
相关产品推荐
相关产品推荐

