Схема БД адресной книги

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

Как вы думаете, как лучше хранить эти данные? Поскольку у пользователей может быть несколько адресов и т. д., полная нормализация приведет к беспорядку. Я думаю об использовании XML, но я не знаком с запросами полей базы данных XML. Смогу ли я по-прежнему искать пользователей по контактной информации?

Я использую SQL Server 2005, если это имеет значение.


person palmsey    schedule 01.09.2008    source источник


Ответы (7)


Рассмотрим две таблицы для людей и их адресов:

People (pid, prefix, firstName, lastName, suffix, DOB, ... primaryAddressTag )

AddressBook (pid, tag, address1, address2, city, stateProv, postalCode, ... )

Первичный ключ (который однозначно идентифицирует каждую строку) людей — pid. PK AddressBook представляет собой композицию pid и тега (pid, tag).

Некоторые примеры данных:

Люди

1, Kirk

2, Spock

Адресная книга

1, home, '123 Main Street', Iowa

1, work, 'USS Enterprise NCC-1701'

2, other, 'Mt. Selaya, Vulcan'

В этом примере у Кирка два адреса: «домашний» и «рабочий». Один из этих двух может (и должен) быть отмечен как внешний ключ (например, перекрестная ссылка) в People в столбце primaryAddressTag.

У Спока есть единственный адрес с пометкой «другой». Поскольку это единственный адрес Спока, значение «другое» должно быть в столбце primaryAddressTag для pid=2.

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

Кроме того, со ссылками FK в primaryAddressTag система базы данных сама будет обеспечивать достоверность тега первичного адреса (с помощью того, что мы, специалисты по базам данных, называем ссылочной целостностью), так что вашему — или любому — приложению не нужно беспокоиться об этом.

person Alan    schedule 14.09.2008

Почему полная нормализация «будет беспорядком»? Это как раз то, что нормализация делает менее беспорядочной.

person John    schedule 01.09.2008

Не бойтесь нормализовать свои данные. Нормализация, как Джон упоминает, является решением, а не проблемой. Если вы попытаетесь денормализовать свои данные только для того, чтобы избежать пары объединений, то вы создадите себе серьезные проблемы в будущем. Попытка рефакторинга такого рода данных после того, как у вас будет набор данных разумного размера, НЕ БУДЕТ УДОВОЛЬСТВИЕМ.

Я настоятельно рекомендую вам проверить Highrise от 36 Signals. Недавно мне его порекомендовали, когда я искал онлайн-менеджера контактов. Это так правильно. На самом деле, мое единственное возражение по поводу сервиса заключается в том, что я считаю платные версии слишком дорогими — вот и все.

На сегодняшний день я не вписываюсь в профиль с однородным адресом. У меня есть 4-5 адресов электронной почты, которые я использую регулярно, 5 телефонных номеров, 3 адреса, несколько веб-сайтов и профилей обмена мгновенными сообщениями, и все это я бы включил в свой контактный профиль. Если вы только начинаете создавать систему управления контактами и не обременены архитектурными ограничениями (представьте, что контакты Gmail привязаны к одному адресу электронной почты), то сделайте своим пользователям одолжение и сделайте свою структуру контактов настолько гибкой (нормализованной), насколько это возможно. возможно.

Привет, - Д.

person dshaw    schedule 16.11.2008

Я знаю о SQLite, но это не очень помогает - я говорю о том, чтобы найти лучшую схему (независимо от базы данных) для хранения этих данных.

person palmsey    schedule 01.09.2008

Согласно Джону, я не вижу проблем с классической нормализованной схемой. Вы не дали много информации, чтобы продолжить, но вы говорите, что между пользователями и адресами существует отношение «один ко многим», поэтому я бы предпочел стандартное решение болота с внешним ключом для пользователя в отношении адреса.

person Rob    schedule 01.09.2008

Если вы предполагаете, что у каждого пользователя есть один или несколько адресов, номер телефона и т. д., у вас может быть таблица «Пользователи», «Таблица адресов» (содержащая первичный ключ, а затем неуникальную ссылку на пользователей), то же самое для телефонные номера — разрешение нескольких строк с одним и тем же внешним ключом UserID, что сделало бы запрос «все адреса для пользователя X» довольно простым.

person James Inman    schedule 01.09.2008

У меня нет скрипта, но есть mySQL, который вы можете использовать. Перед этим я должен упомянуть, что существует два логических подхода к хранению визитных карточек в SQL:

  1. Сохраните всю карту и позвольте базе данных искать (возможно) огромные текстовые строки и обрабатывать их в другой части вашего кода или даже на стороне клиента. например

    CREATE TABLE IF NOT EXISTS vcards (
    name_or_letter varchar(250) NOT NULL,
    vcard text NOT NULL,
    timestamp timestamp по умолчанию CURRENT_TIMESTAMP при обновлении CURRENT_TIMESTAMP,
    PRIMARY KEY (username)
    ) ENGINE = MyISAM CHARSET ПО УМОЛЧАНИЮ = utf8 COLLATE = utf8_bin;

Вероятно, легко реализовать (в зависимости от того, что вы делаете с данными), хотя ваши поиски будут медленными, если у вас много записей. Если это только для вас, то это может сработать (если это хорошо, то это никогда только для вас.) Затем вы можете обработать клиентскую или серверную часть vCard, используя какой-нибудь красивый модуль, который вы поделиться (или кто-то другой поделился с вами).

Я наблюдал за развитием vCard и знаю, что в /когда-нибудь/ в будущем произойдут некоторые изменения, поэтому я использую три таблицы.

Во-первых, это карта (в основном это ссылки на мои существующие таблицы - если вам это не нужно, ваша может быть урезанной версией). Вторые - это определения карт (которые, кажется, называются профилем на языке vCard). В последней находятся все актуальные данные для карт.

Поскольку я позволяю DBIx::Class (да, я один из них) выполнять всю работу с базой данных, (три таблицы), кажется, работает для меня довольно хорошо (хотя, очевидно, вы можете подтянуть типы, чтобы они соответствовали rfc2426, но по большей части каждый фрагмент данных представляет собой просто текстовую строку.)

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

 CREATE TABLE `vCards` (   
 `card_id` int(255) unsigned NOT NULL AUTO_INCREMENT,   
 `card_peid` int(255) DEFAULT NULL COMMENT 'link back to user table',   
 `card_acid` int(255) DEFAULT NULL COMMENT 'link back to account table',      
 `card_language` varchar(5) DEFAULT NULL COMMENT 'en en_GB',
 `card_encoding` varchar(32) DEFAULT 'UTF-8' COMMENT 'why use anything else?',
 `card_created` datetime NOT NULL,  
 `card_updated` datetime NOT NULL,
 PRIMARY KEY (`card_id`) )
 ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='These are the contact cards'

   create table vCard_profile (
    vcprofile_id int(255) unsigned auto_increment NOT NULL,
    vcprofile_version enum('rfc2426') DEFAULT "rfc2426" COMMENT "defaults to vCard 3.0",
    vcprofile_feature char(16) COMMENT "FN to CATEGORIES",
    vcprofile_type enum('text','bin') DEFAULT "text" COMMENT "if it is too large for vcd_value then user vcd_bin",
  PRIMARY KEY (`vcprofile_id`)
) COMMENT "These are the valid types of card entry";
INSERT INTO vCard_profile VALUES('','rfc2426','FN','text'),('','rfc2426','N','text'),('','rfc2426','NICKNAME','text'),('','rfc2426','PHOTO','bin'),('','rfc2426','BDAY','text'),('','rfc2426','ADR','text'),('','rfc2426','LABEL','text'),('','rfc2426','TEL','text'),('','rfc2426','EMAIL','text'),('','rfc2426','MAILER','text'),('','rfc2426','TZ','text'),('','rfc2426','GEO','text'),('','rfc2426','TITLE','text'),('','rfc2426','ROLE','text'),('','rfc2426','LOGO','bin'),('','rfc2426','AGENT','text'),('','rfc2426','ORG','text'),('','rfc2426','CATEGORIES','text'),('','rfc2426','NOTE','text'),('','rfc2426','PRODID','text'),('','rfc2426','REV','text'),('','rfc2426','SORT-STRING','text'),('','rfc2426','SOUND','bin'),('','rfc2426','UID','text'),('','rfc2426','URL','text'),('','rfc2426','VERSION','text'),('','rfc2426','CLASS','text'),('','rfc2426','KEY','bin');

create table vCard_data (
    vcd_id int(255) unsigned auto_increment NOT NULL,
    vcd_card_id int(255) NOT NULL,
    vcd_profile_id int(255) NOT NULL,
    vcd_prof_detail varchar(255) COMMENT "work,home,preferred,order for e.g. multiple email addresses",
    vcd_value varchar(255),
    vcd_bin blob COMMENT "for when varchar(255) is too small",
    PRIMARY KEY (`vcd_id`)
) COMMENT "The actual vCard data";

Это не лучший SQL, но я надеюсь, что это поможет.

person Alexx Roche    schedule 03.07.2012