SQL数据库具有相同属性的多个值 - 最佳实践?

时间:2017-02-20 13:41:26

标签: sql database tsql multivalue

我发现自己的Person表中的一些属性需要保存多个值/选项,这不是一个好的SQL实践,所以我创建了第二个表,如下所示:

在:

Person table
-ID (ex. 101)
-Name (ex. John)
-Accessories (ex. Scarf, Mask, Headband, etc..) - One person can have a combination of this

后:

Person Table
-ID
-Name

PersonDetails Table
-PersonID (FK to Person table)
-Attribute type
-Attribute value

和一个例子:

Person: 
ID:13; Name: John Snow
PersonDetails:
PersonID: 13; Attribute type: Accessories; Attribute value: Scarf
PersonID: 13; Attribute type: Accessories; Attribute value: Mask

你可以看到ID为13的人同时拥有围巾和面具。

这是一个好习惯吗?还有哪些其他方法可以最有效地实现这一目标?

此外,如果有更新,13人没有围巾和面具但只有眼镜? (分别删除2并插入一个新的?这意味着只有一个修改请求的3个查询)

2 个答案:

答案 0 :(得分:5)

我认为这与n:m相关。您需要一张表Person,其中包含ID,姓名和其他人的详细信息。另一张表Accessory,其中包含ID,名称和更多附件的详细信息。第三个表PersonAccessory用于存储PersonID和AccessoryID对(这称为映射表

工作示例(SQL-Server语法)

CREATE TABLE Person(ID INT IDENTITY PRIMARY KEY,Name VARCHAR(100));
INSERT INTO Person VALUES('John'),('Jim');

CREATE TABLE Accessory(ID INT IDENTITY PRIMARY KEY,Name VARCHAR(100));
INSERT INTO Accessory VALUES('Scarf'),('Mask');

CREATE TABLE PersonAccessory(PersonID INT NOT NULL FOREIGN KEY REFERENCES Person(ID)
                            ,AccessoryID INT NOT NULL FOREIGN KEY REFERENCES Accessory(ID));
INSERT INTO PersonAccessory VALUES(1,1),(2,1),(2,2);

SELECT p.Name
      ,a.Name 
FROM PersonAccessory AS pa
INNER JOIN Person AS p ON pa.PersonID=p.ID
INNER JOIN Accessory AS a ON pa.AccessoryID=a.ID;
GO

--DROP TABLE PersonAccessory;
--DROP TABLE Accessory;
--DROP TABLE Person

结果

John    Scarf
Jim     Scarf
Jim     Mask

答案 1 :(得分:0)

这是一个工作示例。看看这个

;with tmp(Personid, name,AttributeType, DataItem, Data) as (
    select Personid, name,'Accessories' AttributeType, LEFT(Accessories, CHARINDEX(',',Accessories +',')-1),
        STUFF(Accessories , 1, CHARINDEX(',',Accessories +','), '')
    from Person
    union all
    select Personid, name,'Accessories' AttributeType, LEFT(Data, CHARINDEX(',',Data+',')-1),
        STUFF(Data, 1, CHARINDEX(',',Data+','), '')
    from tmp
    where Data > ''
    )
    select Personid, name,AttributeType, DataItem
    from tmp
    order by Personid