sql - 用户标签系统设计 - 用户画像数据库设计




针对与数据库无关的应用程序的数据库设计 (12)

一个新的应用程序的数据库设计中 ,我应该考虑哪些应该能够支持最常见的关系数据库系统(SQL Server,MySQL,Oracle,PostgreSQL ...)?

这是值得的吗? 什么是陷阱?


  1. 不要使用存储过程
  2. 不要使用供应商特定的SQL

或者,使用诸如hibernate / nHibernate之类的持久化技术来提取不同DB之间的差异。


人们经常会告诉你的一个答案就是不使用数据库特定的sql,而仅仅是代码来标准化。 他们经常会说只能通过存储过程与数据库进行交流来抽象出任何sql。 这些是错误的答案,只会导致痛苦。 编码为“标准”的SQL几乎是不可能的,因为每个供应商都有不同的解释。

你需要的是具有某种数据库持久层的摘要数据库之间的差异(抱歉,johnstock,这几乎就是你所说的)。 还有许多其他ORM和类似的产品可以为每个平台做到这一点,


在2001年,我开发了一款必须支持Oracle 8,MS SQL Server 2000和MS Jet 3.51(又名Access97)的产品。 从理论上讲,我们可以聘请专家为每个产品和测试过程,确保所有产生相同的结果。 在实践中,有一个倾向于最低的共同标准。

一种方法是在Access / Jet for Oracle和SQL Server中创建链接表,然后专门编写Jet SQL。 这里的问题是Jet SQL语法非常有限。

另一种方法(即使在只使用过一种DBMS产品的系统上也是常用的)是尝试去做更多的工作,而这些工作应该是前端应该做的,而这些工作应该是数据库管理系统的领域。 这里的问题是关于数据完整性往往是灾难性的。 我相信你知道的情况是:应用程序应该避免写入非法数据,但是在数据库管理系统本身没有限制的情况下,应用程序的错误是广泛的。 然后有用户知道如何通过Excel,SQL管理工作室等连接到数据,从而完全绕过应该保证数据的完整性...

就我个人而言,我发现自己正在越来越多地编写代码,只是后来才发现我称之为“可移植性”。 理想情况下,首先是我们支持的所有DBMS都理解的“vanilla”代码,这样我发现了SQL-89和SQL-92标准。 接下来是SQL代码,可以很容易地为每个DBMS翻译(也许使用代码),例如,Oracle使用可怕的外部连接语法,但外部连接的概念在那里; Oracle和SQL Server使用SUBSTRING,但Jet要求关键字是MID $; 等等。最后,还有一些东西需要具体实现,如果可能,尽可能避免重视数据的完整性,功能和性能。

令人高兴的是,在这段时间里,产品已经越来越接近ANSI SQL标准(除了Jet以外,MS已经被MS弃用,现在只能靠MS Access团队保持活力,似乎通过削减安全和复制等主要功能)。 所以我已经习惯于在可能的情况下编写Standard SQL。


如果可以将与平台相关的代码隔离到特定层中,则95%的便携性几乎与便携式一样好。 就像Java被描述为“一次编写一次测试”一样 ,人们仍然需要在每个想要运行的平台上测试应用程序。

如果您对平台特定的代码持谨慎态度,那么您可以使用便携式代码来实现可以以便携方式充分完成的95%以上的功能。 需要在存储过程或其他依赖于平台的构造中完成的其余部分可以构建到一系列依赖于平台的模块中,以形成标准接口。 取决于您使用适合该平台的模块的平台。

这是“测试无处不在”和“构建平台特定模块和测试无处不在”之间的区别。 无论如何,您将需要在所有支持的平台上进行测试 - 您无法脱身。 额外的构建相对较小,并且可能比让一个非常复杂的架构尝试和完全移植这些东西少。


我打算约翰的答案1)不要使用存储过程和2)不要使用供应商特定的SQL,并添加到它。

你还问:“这是值得的吗?” 我会说...也许。 我写了一个基于SQL Server的开源Bug跟踪器BugTracker.NET。 有许多开发者根本不愿意尝试,因为他们喜欢坚持自己熟悉的技术。 而且,当我考虑启动托管服务时,我注意到专用的Linux虚拟服务器比Windows(非虚拟)服务便宜得多。 理论上我可以在单声道下运行C#,但是我的SQL是特定于SQL Server的(即使我不使用存储的特效),这将是一个巨大的努力。

如果你的目标是一个企业/企业市场,你会发现一些商店是严格的甲骨文,或严格的SQL Server,并且你的应用程序可能会被排除在比赛的早期基于其使用的技术。

所以,也许对你开放很重要。 它是什么类型的应用程序? 谁会用它?

你也问:“什么是平价”。 没有测试,因为你走。 如果你打算支持你列出的4个数据库,那么你应该尽早和经常地对它们进行测试,而不是只针对一个,同时认为它很容易转换到其他的。 那时你可能会发现自己在一个建筑的尽头。


我理解这里的其他答案,但为什么不使用存储过程? 是不是把逻辑隐藏起来?


研究数据类型的最低共同点。 例如,SQL Server有一个整数,但Oracle使用一个数字。


简单的答案是坚持标准的功能,或接近标准实施。 这意味着更详细的是:

  • 避免使用数据库过程语言(存储过程或触发器)的任何事情,因为这是系统之间巨大差异的地方。您可能需要使用它们来模拟某些功能,但不要使用它们来创建自己的功能。

  • 从字段本身分离自动增量字段的序列。 这看起来有点为MSSQL强制,但将无需任何仿真修复在Oracle,DB / 2等干净地实施。

  • 保持char和varchar字段低于您所瞄准的一组引擎的最小最大大小。

  • 在编写查询时,请使用完整的JOIN语法,并将JOIN括起来,以便每个连接位于单个表格和括号内的表达式之间。

  • 在代码中保留日期处理逻辑,而不是查询,因为许多日期函数超出了标准。 (例如:如果你想获得过去两周的内容,请在代码中计算两周前的日期,并在查询中使用该日期。)

除此之外,所涉及的努力不应该太令人生畏,所以它可能是值得的。


除了考虑到这里的许多好的和合理的答案之外,我还要补充一点,像ActiveRecord迁移 (从Ruby On Rails,但你可以使用库)可能是有用的。 它将表格创建/更改,适当的列类型,更简单的索引管理和(一定数量)排序抽象为相当简单的描述语言。

存储过程和触发器几乎被忽略,但是如果你要跨平台的话,这种功能应该可能在代码层中。

出于好奇,我已经在Oracle,MS SQL,MySQL和SQLite之间切换了相同的迁移集合,而我发现的最糟糕的问题是我必须确保列名和表名不在保留字列表中数据块。


如果可能,我会避免这样做。 过去我曾与其中几个数据库合作过,他们的速度非常慢(我能想到的一个特别痛苦的例子是呼叫中心应用程序,在繁忙的一天中,从一个屏幕移动到另一个屏幕花了10分钟)编写通用的SQL,而不是使用最适合特定后端的性能调优。


海事组织取决于你正在开发的应用程序的类型:

  1. 一个应用程序,满足一些其他需要,涉及到存储数据,例如商业网站,业务线应用程序,甚至家庭/生活方式的应用程序。
  2. 专门设计用于操纵或管理数据库的应用程序,例如设计工具,建模工具,ETL工具。

对于案例1,只需选择一个最适合您需求的DBMS,并使用其所有专有功能的全部功能进行编码即可。

对于案例2,您可能会发现坚持所有您希望支持的DBMS支持的通用操作子集是非常可行的。


作为对此答案的补充,作为一般规则,不要让服务器生成或计算数据。 总是发送直接的SQL指令,不包括公式。 不要使用默认值属性(或使它们基本,而不是公式)。 不要使用验证规则应该在客户端执行默认值和验证规则。





database-design