地址簿数据库架构

时间:2008-09-01 20:02:15

标签: schema microformats vcard normalizing hcard

我需要为用户存储联系信息。我想在页面上以hCard的形式显示此数据,并可以vCard下载。我也希望能够通过电话号码,电子邮件等搜索数据库。

您认为存储此数据的最佳方式是什么?由于用户可能有多个地址等,因此完全规范化将是一团糟。我正在考虑使用XML,但我不熟悉查询XML数据库字段。我仍然可以通过联系信息搜索用户吗?

我正在使用SQL Server 2005,如果这很重要。

7 个答案:

答案 0 :(得分:7)

考虑人员及其地址的两个表:

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

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

人员的主键(唯一标识每一行)为pid。 AddressBook的PK是pid和标记(pid, tag)的组合。

一些示例数据:

1, Kirk

2, Spock

地址簿

1, home, '123 Main Street', Iowa

1, work, 'USS Enterprise NCC-1701'

2, other, 'Mt. Selaya, Vulcan'

在这个例子中,Kirk有两个地址:一个是“家”,一个是“工作”。其中一个可以(并且应该)在primaryAddressTag列的People中注明为外键(如交叉引用)。

Spock有一个带有“其他”标签的地址。由于这是Spock唯一的地址,因此pid = 2的primaryAddressTag列应该包含'other'值。

这种模式具有很好的效果,可以防止同一个人通过意外重用标签来复制他们自己的任何地址,同时允许所有其他人使用他们喜欢的任何地址标签。

此外,对于primaryAddressTag中的FK引用,数据库系统本身将强制执行主要地址标记的有效性(通过我们数据库极客称之为引用完整性的内容),以便您或任何应用程序不需要担心它。

答案 1 :(得分:3)

为什么完成标准化“一团糟”?这正是规范化不那么混乱的事情。

答案 2 :(得分:3)

不要害怕规范化您的数据。规范化,如John mentions,解决方案不是问题。如果你试图对数据进行非规范化以避免一些联接,那么你将来会给自己带来严重的麻烦。在拥有合理大小的数据集之后,尝试重新构建此类数据将不会有用。

我强烈建议你从36个信号中查看Highrise。最近我在寻找在线联系经理时向我推荐。它做得非常好。实际上,到目前为止,我对该服务的唯一反对意见是,我认为付费版本太贵了 - 就是这样。

就目前而言,我不适合平坦的地址档案。我有4-5个经常使用的电子邮件地址,5个电话号码,3个地址,几个网站和IM个人资料,所有这些都包含在我的联系人资料中。如果您现在开始构建联系人管理系统并且您不受架构限制(认为gmail cantacts键入单个电子邮件地址),那么请帮助您的用户并使您的联系人结构灵活(规范化)为可能的。

干杯,-D。

答案 3 :(得分:1)

我知道SQLite,但这并没有什么帮助 - 我正在谈论找出用于存储这些数据的最佳模式(无论数据库)。

答案 4 :(得分:1)

Per John,我不知道经典规范化架构会出现什么问题。你还没有提供太多的信息,但是你说用户和地址之间存在一对多的关系,所以我会在地址关系中为用户提供一个带有外键的沼泽标准解决方案。

答案 5 :(得分:0)

如果您假设每个用户都有一个或多个地址,电话号码等,您可以拥有“用户”表,“地址表”(包含主键,然后是对用户的非唯一引用),电话号码相同 - 允许多行具有相同的UserID外键,这将使查询“用户X的所有地址”变得非常简单。

答案 6 :(得分:0)

我没有脚本,但我确实有你可以使用的mySQL。在此之前,我应该提到在SQL中存储vCard似乎有两种逻辑方法:

  1. 存储整张卡片,让数据库搜索(可能)巨大的文本字符串,并在代码的另一部分甚至客户端处理它们。例如

    CREATE TABLE IF NOT NOT EXISTS vcards
     name_or_letter varchar(250)NOT NULL,
     vcard文本NOT NULL,
     更新CURRENT_TIMESTAMP时,timestamp时间戳默认为CURRENT_TIMESTAMP,
     主要关键(username
    )ENGINE = MyISAM DEFAULT CHARSET = utf8 COLLATE = utf8_bin;

  2. 可能很容易实现,(取决于您对数据的处理方式),但如果您有很多条目,搜索速度会很慢。 如果这只适合你,那么这可能会有效(如果它有任何优点,那么永远不会只适合你。)然后你可以使用一些漂亮的模块处理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,但我希望有所帮助。