是否有便携式SQL这样的东西?

时间:2011-04-13 13:48:19

标签: sql portability

根据我的经验,即使有一个SQL标准,编写在大量RDBMS上运行,未经修改的SQL也很困难。

因此,我想知道是否存在可用于所有主要RDBMS的SQL子集(包括DDL,模式等),包括PostgreSQL,MySQL,SQL Server以及最后但并非最不重要的,甲骨文。编写可移植SQL时应该避免哪些陷阱?

顺便说一句,是否有一个项目的目标是将有效的SQL子集转换为所有这些供应商使用的特定方言?我知道Hibernate和其他ORM系统必须这样做,但我不想要ORM,我想编写直接数据库SQL。

谢谢!

5 个答案:

答案 0 :(得分:4)

问题是某些DBMS甚至忽略了最简单的标准(例如引用字符或字符串连接)。

因此,以下(100%ANSI SQL)不会在每个DBMS上运行:

UPDATE some_table
    SET some_column = some_column || '_more_data';

我甚至没有考虑过更高级的SQL标准,比如递归公用表表达式(甚至那些支持它的表达式并不总是符合要求)或窗口函数(有些只实现一个非常窄的子集,有些不支持所有选项) )。

关于DDL,数据类型存在问题。 DATE在任何地方都不一样,就像TIMESTAMP一样。并非每个DBMS都有BOOLEAN类型或TIME类型。

当涉及到约束或域时,您会获得更多差异。

简而言之:除非你真的,真的需要独立于DBMS,不要为此烦恼。

说了这么多:如果您确实可以选择专有语法和标准语法,请选择标准语法(OUTER JOIN vs (+)*=decode vs CASEnvlcoalesce等等。

答案 1 :(得分:2)

在每个RDBMS中,列为ANSI兼容的内容在所有内容中应该是相同的,因为这是真正的标准。但是,通过仅使用ANSI(即便携式)内容,您就会失去优化的,特定于供应商的功能。另外,仅仅因为PostgreSQL实现ANSI函数并不意味着它可以在任何其他RDBMS中使用(但如果它可用,那么它应该工作相同)。

就个人而言,我认为真正可移植的SQL代码或项目没有任何价值可归一化到最小公分母集,因为每个特定的RDBMS都有不同的优化。没有通用的应用语言。如果你正在使用C#,那么你就不会想要使用只能在PHP或JAVA中找到的东西。所以,只需拥抱你所在的平台:)。

编辑:如果您正在编写可以连接到多个不同RDBMS的应用程序,那么您可能需要为每个特定平台找到适当的SQL,就像每个ORM的作者必须这样做。

答案 2 :(得分:1)

简单查询几乎总是可移植的。不幸的是,您提供的SQL供应商列表在标准合规性方面差异很大。在遵守ANSI SQL标准方面,MS SQL Server是您列出的最重要的,而且在标准合规性方面,MySQL和Oracle都是非常糟糕的。当然,这并不是说它们是糟糕的RDBMS引擎或者你不能用它们编写强大的查询,但是它们对标准的遵守并不完全是它们所知道的。

请注意,您已经省略了该列表中的一些大型RDBMS播放器,即Sybase和IBM的DB2。这两个通常比其他标准更符合标准,这是值得的。

答案 3 :(得分:1)

我可以在一个产品上编写SQL代码并期望它在不修改的情况下在另一个产品上工作的理想是一个不可能实现的梦想。

我更倾向于将“可移植性”视为将代码移动到另一个SQL产品是多么容易,或者至关重要的是同一SQL产品的更高版本,并指出已建立的SQL产品往往会移动对于 SQL标准(例如SQL-92的UPDATE需要标量子查询因此是冗长的,SQL Server早期提供了专有的JOIN..FROM语法,然后为SQL Server 2008提供了{{1}支持的语法扩展了标准SQL的MERGE)。

根据经验,使用SQL产品支持它的标准SQL代码(例如MERGE而不是SQL Server的CURRENT_TIMESTAMP),否则更喜欢容易映射到标准SQL代码的专有代码(例如SQL Server的getdate()使用宏轻松映射到标准SQL的SUBSTRING()。请注意,SQL标准之外的某些函数对于SQL产品是通用的(例如,大多数/所有函数都将具有SUBSTRING()函数或运算符。)

答案 4 :(得分:1)

我使用Alpha Five构建Web应用程序,它具有一个名为“Portable SQL”的功能。大约有200个“便携功能”。如果我使用可移植性功能,它将自动转换为本机SQL以适应我碰巧使用的任何引擎。

因此,如果我编写“SELECT now()FROM clients”,now()作为可移植性函数,则该语法将根据我碰巧使用的内容自动转换为本机语言。它们支持22种不同的SQL引擎。

  • DB2-SELECT CURRENT TIMESTAMP AS Expr1 FROM clients
  • MYSQL-SELECT Now()AS Expr1 FROM client
  • MSSQL-SELECT CURRENT_TIMESTAMP AS Expr1 FROM clients
  • SYBASE-SELECT getdate()AS Expr1 FROM client
  • ODBC-SELECT {fn Now()} AS Expr1 FROM client