SQL:多值属性

时间:2012-01-15 08:18:25

标签: sql database

我创建了一个包含公司信息的表。一个属性是他们的电话号码。公司可以有很多电话号码。

如何在SQL中创建多值属性?

4 个答案:

答案 0 :(得分:16)

在另一张表格中:

CREATE TABLE Company
(
  Id int identity primary key, 
  Name nvarchar(100) not null UNIQUE --UNIQUE is optional
)
GO
CREATE TABLE CompanyPhones
(
  Id int identity primary key, 
  Phone nvarchar(100) not null, 
  CompanyId int NOT NULL REFERENCES Company(Id) ON DELETE CASCADE
)

如何使用这些结构:

SELECT CompanyPhones.Phone
FROM Company
JOIN CompanyPhones
  ON Company.Id = CompanyPhones.CompanyId
WHERE Company.Name=N'Horns and Hoogs Ltd.'

答案 1 :(得分:8)

关系数据库中通常没有多值属性。

您的问题的可能解决方案:

  1. 创建一个单独的表,用于存储按主键引用公司表的电话号码,并且每个公司包含不确定的行数。

    例如,如果您的表格company包含字段id, name, address, ...,那么您可以创建一个包含字段companyphones的表companyid, phone

  2. (一般情况下不推荐,但如果您只需要在网站上显示手机列表,这可能是一个选项)使用varchar(...)或文本在单个字段中存储电话并在两者之间添加分隔符号。

答案 2 :(得分:6)

除Oleg和Sergey的答案外,第三个选项可能是在公司表上创建多个电话字段 - 例如,对于主交换机和传真线,SwitchboardPhoneFaxNumber,分别

这种类型的解决方案通常被视为非规范化的一种形式,并且通常仅适用于存在少量多个选项的情况,每个选项都有明确定义的角色。

因此,例如,这是表示联系人列表中的固定电话和移动电话号码的常用方法,但完全不适合公司内所有电话分机的列表。

答案 3 :(得分:4)

在RDBMS的不同实现中存在一些可能性。

例如,在 PostgreSQL 中,您可以使用arrayhstore甚至JSON (in 9.3 version)

create table Company1 (name text, phones text[]);

insert into Company1
select 'Financial Company', array['111-222-3333', '555-444-7777'] union all
select 'School', array['444-999-2222', '555-222-1111'];

select name, unnest(phones) from Company1;

create table Company2 (name text, phones hstore);

insert into Company2
select 'Financial Company', 'mobile=>555-444-7777, fax=>111-222-3333'::hstore union all
select 'School', 'mobile=>444-999-2222, fax=>555-222-1111'::hstore;

select name, skeys(phones), svals(phones) from Company2    

<强> sql fiddle demo

您还可以在这些字段上创建索引 - https://dba.stackexchange.com/questions/45820/how-to-properly-index-hstore-tags-column-to-faster-search-for-keysCan PostgreSQL index array columns?

SQL Server 中,您可以使用xml数据类型来存储多值:

create table Company (name nvarchar(128), phones xml);

insert into Company
select 'Financial Company', '<phone type="mobile">555-444-7777</phone><phone>111-222-3333</phone>' union all
select 'School', '<phone>444-999-2222</phone><phone type="fax">555-222-1111</phone>'

select
    c.name,
    p.p.value('@type', 'nvarchar(max)') as type,
    p.p.value('.', 'nvarchar(max)') as phone
from Company as c
    outer apply c.phones.nodes('phone') as p(p)

<强> sql fiddle demo

您还可以在xml类型列上create xml indexes