数据库无关应用程序的数据库设计

时间:2008-10-15 08:28:22

标签: sql database database-design

对于应该能够支持最常见的关系数据库系统(SQL Server,MySQL,Oracle,PostgreSQL ......)的新应用程序,我必须考虑在数据库设计中吗?< / p>

是否值得努力?有什么陷阱?

17 个答案:

答案 0 :(得分:15)

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

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

  • 从字段本身中分离自动增量字段的序列。对于MSSQL来说,这看起来有点强迫,但在Oracle,DB / 2等中可以完全实现,而无需任何仿真修复。

  • 将char和varchar字段保持在您所针对的引擎集的最小最大大小之下。

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

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

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

答案 1 :(得分:6)

我目前支持Oracle,MySQL和SQLite。说实话,这很难。 一些建议是:

  • 避免存储过程,但您可能需要它们来模拟某些平台上的缺失功能(见下文)
  • 学习如何使用触发器,因为你需要它们来模拟缺失的功能(例如,使用Oracle你没有自动增量,所以你需要模拟它,并且选择是使用触发器)
  • 有一个不错的测试环境,因为你需要先测试很多SQL,然后才能确定它是在你所有平台上做的。

值得吗......好吧。在商业上,它对于企业级应用程序是值得的,但对于博客或说网站,如果可以,您可以坚持使用一个平台。

答案 2 :(得分:6)

如果我是你,我会认真考虑你的投资回报

总是听起来是一个好主意,能够随时联系任何后端或改变后端,但根据我的经验,这很少发生在真实世界中。 / p>

可能会发现,只支持Oracle&amp; A就可以覆盖95%的潜在客户。 SQL Server(或MySQL&amp; SQL Server,或......等)。

在继续研究之前进行研究,祝你好运!

答案 3 :(得分:4)

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

你需要的是拥有某种数据库持久层抽象数据库之间的差异(对不起johnstock,这几乎就是你所说的)。每个平台都有许多其他ORM和类似产品,

答案 4 :(得分:4)

我将讨论johnstok的回答1)不要使用存储过程和2)不要使用供应商特定的SQL,并添加它。

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

如果你的目标是商业/企业市场,你会发现一些商店是严格的Oracle,或严格的SQL Server,并且你的应用程序可能会在竞争的早期轮次基于其使用的技术被排除

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

你也问过,“什么是ptifalls”。你不去测试。如果你计划支持你列出的4个dbs,那么你应该尽早和经常测试它们,而不是仅仅针对一个,同时认为它很容易转换为其他的。到那时你可能会发现自己处于一个建筑的死胡同里。

答案 5 :(得分:4)

2001年,我研发了一款必须支持Oracle 8,MS SQL Server 2000和MS Jet 3.51(a.k.a. Access97)的产品。理论上,我们可以为这些产品中的每一个都使用专家,并且测试过程确保所有产品都能产生相同的结果。在实践中,存在着最低共同点的趋势。

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

另一种方法(即使在只使用过一个DBMS产品的系统上也常用!)是尝试做更多应该在前端应该做的工作,这应该是DBMS的领域。这里的问题是数据完整性通常是灾难性的。我确定你知道这种情况:应用程序应该避免编写非法数据,但DBMS本身没有约束,它对应用程序错误是开放的。然后有用户知道如何通过Excel,SQL Management Studio等连接数据,从而完全绕过应该确保数据完整性的应用程序......

就个人而言,我发现自己越来越多地在我后来发现的被称为“可移植性”的滑动范围内编写代码。理想情况下,首先是我们支持的所有DBMS都能理解的“vanilla”代码,并且这样做我发现了SQL-89和SQL-92标准。接下来是可以为每个DBMS轻松翻译(可能使用代码)的SQL代码,例如Oracle使用了那种可怕的外连接语法,但是外连接的概念就在那里; Oracle和SQL Server使用SUBSTRING,但Jet要求关键字为MID $;最后,有些东西只需要特定于实现,显然可以避免,尽管仍然在适当考虑数据完整性,功能和性能。

令人高兴的是,在此期间,产品已逐渐接近ANSI SQL标准(除了被MS弃用的Jet,现在MS Access团队只能通过削减安全和复制等主要功能来保持活力)。所以我一直保持着编写标准SQL的习惯。

答案 6 :(得分:2)

保持字段和表名称短(<30个字符)且不区分大小写。例如TABLE_NAME和FIELD_NAME

答案 7 :(得分:1)

如果可以将平台相关代码隔离到特定层,95%便携式几乎与便携式一样好。正如Java被描述为'Write once test everywhere'一样,仍然需要在您打算运行它的每个平台上测试应用程序。

如果您对特定于平台的代码保持谨慎,则可以使用便携式代码实现95%以上的功能,这些功能可以通过便携方式充分完成。需要在存储过程或其他依赖于平台的构造中完成的其余部分可以构建到与标准接口相关的一系列依赖于平台的模块中。根据平台,您可以使用适合该平台的模块。

这是'Test everywhere'和'Build platform specific modules and Test everywhere'之间的区别。无论如何,您将需要在所有支持的平台上进行测试 - 您无法摆脱这种情况。额外的构建相对较小,可能比制作一个真正复杂的架构试图完全移植这些东西。

答案 8 :(得分:1)

作为this answer的补充,并且作为一般规则,不要让服务器生成或计算数据。始终发送直接SQL指令,不包括公式。不要使用默认值属性(或使它们成为基本属性,而不是公式)。不要使用验证规则 默认值和验证规则都应该在客户端实现。

答案 9 :(得分:0)

IMO取决于您正在开发的应用类型:

  1. 满足其他需要的应用程序,其恰好涉及存储数据,例如:商业网站,商业应用程序,甚至家庭/生活方式应用程序。
  2. 专门用于操作或管理数据库的应用程序,例如设计工具,建模工具,ETL工具。
  3. 对于案例1,只需选择一个最适合您需求的DBMS,并使用其所有专有功能的全部功能来编写代码。

    对于案例2,您可能会发现坚持您打算支持的所有DBMS支持的公共操作子集是完全可行的。

答案 10 :(得分:0)

  1. 不要使用存储过程
  2. 不要使用特定于供应商的SQL
  3. 或者,使用hibernate / nHibernate等持久性技术来抽象出不同数据库之间的差异。

答案 11 :(得分:0)

首先要考虑的是,独立完成的成本是否低于依赖于数据库的成本。我认为有些时候对某些能够为客户提供选择的产品很重要,但是它们会丢失很多数据库功能(这意味着需要再次编写代码)。

对于大客户(大型应用程序),他们必须完全依赖于数据库。对于少量定制,在一台服务器(或两台)上安装Oracle XE和MySQL是一件很麻烦的事。

实际上,我更喜欢使用多个数据库,并且应用程序知道哪个数据库是“abastract”代码。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

规则1:不要使用特定于数据库的功能

规则2:不要使用存储过程。

规则3:如果你违反规则1,那么也要违反规则2.

有很多关于不使用存储过程的评论。这是因为语法/语义非常不同,因此移植它们很困难。您不需要重写和重新测试的大量代码。

如果您确定需要使用特定于数据库的功能,则应将这些详细信息隐藏在存储过程后面。调用不同数据库的存储过程都非常相似。在用PL / SQL编写的过程中,您可以使用任何有用的Oracle构造。然后,您需要为其他目标数据库编写等效项。这样,特定于数据库的部分仅在该数据库中。

答案 14 :(得分:0)

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

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

出于好奇,我在Oracle,MS SQL,MySQL和SQLite之间切换了相同的迁移集,我遇到的最严重的问题是发现我必须确保我的列和表名不在保留字的联合中跨DB的列表。

答案 15 :(得分:0)

我理解其他答案,但为什么不使用存储过程?这样逻辑是不是被隐藏了?

答案 16 :(得分:0)

预先研究数据类型的最小公分母。例如,SQL Server有一个整数但Oracle使用数字。