Подтвердить что ты не робот

SQL: многозначные атрибуты

Я создал таблицу, содержащую информацию о компании. Одним из атрибутов является их номер телефона. У компании может быть много телефонных номеров.

Как создать многозначные атрибуты в SQL?

4b9b3361

Ответ 1

В отдельной таблице, например:

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.'

Ответ 2

В реляционных базах данных обычно нет такой вещи, как многозначный атрибут.

Возможные решения для вашей проблемы:

  • Создайте отдельную таблицу для хранения телефонных номеров, которая ссылается на таблицу вашей компании по первичному ключу и содержит неопределенное количество строк для каждой компании.

    Например, если у вас есть таблица company с полями id, name, address, ..., вы можете создать таблицу companyphones с полями companyid, phone.

  • (НЕ рекомендуется в целом, но если вам нужно только показать список телефонов на веб-сайте, это может быть вариант) Хранение телефонов в одном поле с использованием varchar (...) или текста и добавление разделителей между числа.

Ответ 3

В дополнение к ответам Олега и Сергея третий вариант может заключаться в создании нескольких телефонных полей в таблице компаний - например, SwitchboardPhone и FaxNumber для основного коммутатора и линии факса соответственно.

Этот тип решения обычно рассматривается как форма денормализации и, как правило, подходит только там, где имеется небольшое количество множественных опций, каждая из которых имеет четко определенную роль.

Так, например, это довольно распространенный способ отображения номеров стационарных и мобильных/мобильных телефонов для таблицы списка контактов, но будет полностью непригодным для списка всех телефонных номеров внутри компании.

Ответ 4

В различных реализациях РСУБД есть некоторые возможности.

Например, в PostgreSQL вы можете использовать array или hstore или даже JSON (в версии 9.3):

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

Вы также можете создавать индексы в этих полях - https://dba.stackexchange.com/info/45820/how-to-properly-index-hstore-tags-column-to-faster-search-for-keys, Может ли столбцы столбцов столбца PostgreSQL?

В SQL Server вы можете использовать xat datatype для хранения многозначных значений:

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

Вы также можете создать индексы xml в столбце типа XML.