我需要存储用户的联系信息。 我想在页面上将此数据显示为 hCard 并可作为 vCard。 我还希望能够通过电话号码、电子邮件等搜索数据库。
您认为存储这些数据的最佳方式是什么? 由于用户可能有多个地址等,因此完全规范化会很混乱。 我正在考虑使用 XML,但我不熟悉查询 XML 数据库字段。 我仍然可以通过联系信息搜索用户吗?
我正在使用 SQL Server 2005,如果这很重要的话。
I need to store contact information for users. I want to present this data on the page as an hCard and downloadable as a vCard. I'd also like to be able to search the database by phone number, email, etc.
What do you think is the best way to store this data? Since users could have multiple addresses, etc complete normalization would be a mess. I'm thinking about using XML, but I'm not familiar with querying XML db fields. Would I still be able to search for users by contact info?
I'm using SQL Server 2005, if that matters.
发布评论
评论(7)
我没有脚本,但我有 mySQL 可供您使用。 在此之前,我应该提到,在 SQL 中存储 vCard 似乎有两种逻辑方法:
存储整个卡片并让数据库搜索(可能)巨大的文本字符串,并在代码的另一部分甚至是处理它们客户端。 例如
如果不存在则创建表
vcards
(name_or_letter
varchar(250) NOT NULL,vcard
文本不为空,timestamp
更新 CURRENT_TIMESTAMP 时的时间戳默认为 CURRENT_TIMESTAMP,主键(
用户名
)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
可能很容易实现(取决于您对数据的处理),但如果您有很多条目,您的搜索将会很慢。
如果这只适合你,那么这可能会起作用,(如果它有任何好处,那么它永远不会只适合你。)然后,你可以使用你喜欢的一些漂亮的模块来处理 vCard 客户端或服务器端。分享,(或其他人与您分享。)
我见证了 vCard 的发展,并且知道将会有
将来某个时间会发生一些变化,所以我使用三个表。
第一个是卡片(这主要链接回我现有的表格 - 如果您不需要它,那么您的可以是缩减版本)。
第二个是卡定义(在 vCard 术语中似乎称为配置文件)。
最后是卡片的所有实际数据。
因为我让 DBIx::Class(是的,我是其中之一)完成所有数据库工作,(三个表)似乎对我来说工作得很好,
(尽管显然您可以收紧类型以更紧密地匹配 rfc2426 ,
但在大多数情况下,每条数据只是一个文本字符串。)
我没有规范化该人的地址的原因是我已经有了一个
我的数据库中的地址表,这三个仅用于非用户联系方式。
这不是最好的 SQL,但我希望能有所帮助。
I don't have a script, but I do have mySQL that you can use. Before that I should mentioned that there seem to be two logical approaches to storing vCards in SQL:
Store the whole card and let the database search, (possibly) huge text strings, and process them in another part of your code or even client side. e.g.
CREATE TABLE IF NOT EXISTS
vcards
(name_or_letter
varchar(250) NOT NULL,vcard
text NOT NULL,timestamp
timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,PRIMARY KEY (
username
)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Probably easy to implement, (depending on what you are doing with the data) though your searches are going to be slow if you have many entries.
If this is just for you then this might work, (if it is any good then it is never just for you.) You can then process the vCard client side or server side using some beautiful module that you share, (or someone else shared with you.)
I've watched vCard evolve and know that there is going to be
some change at /some/ time in the future so I use three tables.
The first is the card, (this mostly links back to my existing tables - if you don't need this then yours can be a cut down version).
The second are the card definitions, (which seem to be called profile in vCard speak).
The last is all the actual data for the cards.
Because I let DBIx::Class, (yes I'm one of those) do all of the database work this, (three tables) seems to work rather well for me,
(though obviously you can tighten up the types to match rfc2426 more closely,
but for the most part each piece of data is just a text string.)
The reason that I don't normalize out the address from the person is that I already have an
address table in my database and these three are just for non-user contact details.
This isn't the best SQL but I hope that helps.
如果您假设每个用户都有一个或多个地址、电话号码等,则可以有一个“用户”表、一个“地址表”(包含主键,然后包含对用户的非唯一引用),对于电话号码 - 允许多行具有相同的 UserID 外键,这将使查询“用户 X 的所有地址”变得非常简单。
If you assume each user has one or more addresses, a telephone number, etc., you could have a 'Users' table, an 'Addresses Table' (containing a primary key and then non-unique reference to Users), the same for phone numbers - allowing multiple rows with the same UserID foreign key, which would make querying 'all addresses for user X' quite simple.
根据约翰的说法,我不明白经典规范化模式会出现什么问题。 您没有提供太多信息,但您说用户和地址之间存在一对多关系,因此我会选择一个标准解决方案,在地址关系中具有用户的外键。
Per John, I don't see what the problem with a classic normalised schema would be. You haven't given much information to go on, but you say that there's a one-to-many relationship between users and addresses, so I'd plump for a bog standard solution with a foreign key to the user in the address relation.
我知道 SQLite,但这并没有真正的帮助 - 我正在谈论找出存储此数据的最佳模式(无论数据库如何)。
I'm aware of SQLite, but that doesn't really help - I'm talking about figuring out the best schema (regardless of the database) for storing this data.
不要害怕标准化您的数据。 标准化,就像John提到的一样,是解决方案而不是问题。 如果您只是为了避免几次连接而尝试对数据进行非规范化,那么您将来会给自己带来严重的麻烦。 在拥有合理大小的数据集后尝试重构此类数据不会很有趣。
我强烈建议您查看 36 Signals 的 Highrise。 最近我在寻找在线联系人管理器时向我推荐了它。 它做得非常正确。 事实上,到目前为止,我对该服务唯一的反对意见是我认为付费版本太贵了——仅此而已。
就目前情况而言,我不适合单一的地址配置文件。 我有 4-5 个经常使用的电子邮件地址、5 个电话号码、3 个地址、几个网站和 IM 个人资料,所有这些我都会包含在我的联系资料中。 如果您现在开始构建联系人管理系统并且不受架构限制的阻碍(认为 gmail cantacts 被锁定到单个电子邮件地址),那么请帮您的用户一个忙,并使您的联系人结构像下面一样灵活(规范化)可能的。
干杯,-D。
Don't be afraid of normalizing your data. Normalization, like John mentions, is the solution not the problem. If you try to denormalize your data just to avoid a couple joins, then you're going to cause yourself serious trouble in the future. Trying to refactor this sort of data down the line after you have a reasonable size dataset WILL NOT BE FUN.
I strongly suggest you check out Highrise from 36 Signals. It was recently recommended to me when I was looking for an online contact manager. It does so much right. Actually, my only objection so far with the service is that I think the paid versions are too expensive -- that's all.
As things stand today, I do not fit into a flat address profile. I have 4-5 e-mail addresses that I use regularly, 5 phone numbers, 3 addresses, several websites and IM profiles, all of which I would include in my contact profile. If you're starting to build a contact management system now and you're unencumbered by architectural limitations (think gmail cantacts being keyed to a single email address), then do your users a favor and make your contact structure as flexible (normalized) as possible.
Cheers, -D.
为什么完全正常化会“一团糟”? 这正是标准化可以减少混乱的事情。
Why would complete normalization "be a mess"? This is exactly the kind of thing that normalization makes less messy.
考虑两个 People 表及其地址:
People 的主键(唯一标识每一行)是
pid
。 AddressBook的PK是pid和tag(pid, tag)
组成。一些示例数据:
People
AddressBook
在此示例中,Kirk 有两个地址:一个是“家庭”,一个是“工作”。 这两者之一可以(并且应该)在 PrimaryAddressTag 列的
People
中被标记为外键(如交叉引用)。Spock 有一个带有“其他”标签的地址。 由于这是 Spock 的唯一地址,因此 pid=2 的值“other”应该出现在
primaryAddressTag
列中。这种模式具有很好的效果,可以防止同一个人通过意外地重复使用标签来复制自己的任何地址,同时允许所有其他人使用他们喜欢的任何地址标签。
此外,通过
primaryAddressTag
中的FK引用,数据库系统本身将强制主地址标签的有效性(通过我们数据库极客称为引用完整性的东西),以便您的或任何应用程序不需要担心它。Consider two tables for People and their addresses:
The Primary Key (that uniquely identifies each and every row) of People is
pid
. The PK of AddressBook is the composition of pid and tag(pid, tag)
.Some example data:
People
AddressBook
In this example, Kirk has two addresses: one 'home' and one 'work'. One of those two can (and should) be noted as a foreign key (like a cross-reference) in
People
in the primaryAddressTag column.Spock has a single address with the tag 'other'. Since that is Spock's only address, the value 'other' ought to go in the
primaryAddressTag
column for pid=2.This schema has the nice effect of preventing the same person from duplicating any of their own addresses by accidentally reusing tags while at the same time allowing all other people use any address tags they like.
Further, with FK references in
primaryAddressTag
, the database system itself will enforce the validity of the primary address tag (via something we database geeks call referential integrity) so that your -- or any -- application need not worry about it.