5

我们在一个项目中使用 Oracle,并希望也支持 MySQL。他们的 SQL 方言有多接近?

是否有可能在没有太多体操的情况下为两者使用相同的 SQL 源?

细节:

  • 我们正在使用 iBatis,这是一个持久性管理器,可以将 SQL 语句干净地隔离到资源文件中。但是我们在 SQL 级别工作,这有其优点(和缺点)。
  • 我们不希望迁移到像 Hibernate 这样的对象关系映射器,这将完全保护我们免受方言差异的影响。
  • 我们努力保持 Oracle SQL 的通用子集。
  • 没有 PL/SQL。
  • 我们不使用存储过程或触发器(无论如何)。
  • 我们使用检查约束、唯一约束和外键约束。
  • 我们使用 ON DELETE CASCADEs。
  • 我们使用事务(在 iBatis API 级别完成)。
  • 我们在查询中调用了一些 Oracle 时间戳函数。
  • 我们将使用带有 MySQL 的 InnoDB 存储引擎(它支持事务和约束)。

所以你的想法是什么?我们是否需要维护两组不同的 iBatis SQL 资源文件,一个用于每种方言,或者是否有可能拥有一组同时支持 MySQL 和 Oracle 的 SQL?

最后更新:感谢所有答案,尤其是指向 Troels Arvin 的差异页面的指针。真的很遗憾,标准不是更多,嗯,标准。对我们来说,问题是 MySQL 自动增量与 Oracle 序列,MySQL LIMIT 与 Oracle Rowumber(),也许还有一两个奇怪的函数。正如@mjv 指出的那样,大多数其他东西都应该很容易转移,以一些编辑为模,以确保我们使用 SQL-92。更大的问题是某些查询可能需要在每个 DBMS 中进行不同的手动优化。

4

5 回答 5

9

预计路上会有一些小颠簸,但总的来说应该相对容易。

从您当前使用的功能列表中,应该只有一些句法或语义差异,通常很容易修复或解释。您不使用 PL/SQL 和/或存储过程这一事实是一个优点。一个好的经验法则是尝试并坚持大多数 DBMS 支持的 SQL-92,尤其是 Oracle 和 MySQL。(请注意,这不是当前的 SQL 标准,即 SQL-2008)。

一些不同之处:

  • “LIMIT”是一个著名的:为了限制要在结果列表中检索的行数,MySQL 使用 LIMIT n,在查询结束时,Oracle 在 WHERE 子句中使用 RowNumber() (这很痛苦,对你来说也是需要在 SELECT 列表中引用它...)
  • 有些数据类型是不同的。我认为主要是布尔值(但谁使用它;-))还有一些我认为与 DATETIME 类型/格式的细微差别。
  • 某些函数名称不同(SUBSTRING 与 SUBSTR 等...)

刚刚发现似乎是关于 SQL 实现之间差异的一个很好的资源

阅读其他人的回复,是的,DDL,可能是个问题。我打折这可能是因为许多应用程序不需要 DDL,您只需一次设置数据模式等,然后只需使用 SQL 查询、添加或更新数据。

于 2009-11-14T04:42:20.007 回答
7

我认为使用 MySQL 和 Oracle 维护一组 SQL 资源文件有几个缺点,因为在向后兼容和解决特定问题之间陷入了困境。最好每个 SQL 引擎都有一个 sql,从而最大限度地发挥每个 SQL 引擎的能力。

在宣传册中看起来相同的功能可能会以非常不同的方式实现。

看这些例子

限制结果集

MYSQL

SELECT columns
FROM tablename
ORDER BY key ASC
LIMIT n

甲骨文

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
    columns
  FROM tablename
)
WHERE rownumber <= n

限制—带偏移

MYSQL

SELECT columns
FROM tablename
ORDER BY key ASC
LIMIT n OFFSET skip

甲骨文

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rn,
    columns
  FROM tablename
)
WHERE rn > skip AND rn <= (n+skip)

您可以查看不同 SQL 实现的比较

于 2009-11-14T04:47:22.790 回答
4

除了其他人提到的东西之外,oracle 和 mysql 处理外连接的方式完全不同。实际上,Oracle 提供了一种 mySql 无法处理的语法,但 Oracle 会处理标准语法。

仅甲骨文:

SELECT a.foo, b.bar
  FROM a, b
 WHERE a.foo = b.foo(+)

mysql 和甲骨文:

SELECT a.foo, b.bar
     FROM a 
LEFT JOIN b 
       ON (a.foo=b.foo)

所以你可能需要转换一些外连接。

于 2009-11-16T02:35:44.457 回答
3

你肯定无法保持你的 DDL 不变。就 DML 而言,有许多相似之处(每个数据库都支持 ANSI SQL 标准的核心子集),但也存在一些差异。

首先,MySQL 使用自动递增值,Oracle 使用序列。可以解决这个问题(Oracle 端的序列 + 触发器以模拟自动增量),但它就在那里。内置函数完全不同。

基本上,取决于您打算使用什么,它可能会或可能不会为两者保留一组语句。顺便说一句,即使使用 Hibernate 方言,也不总是可能有相同的查询集 - HQL 很棒,但并不总是足够。

于 2009-11-14T04:42:24.687 回答
2

Oracle 将空字符串视为空值。MySQL 将空字符串视为空字符串,将空字符串视为空字符串。

于 2009-11-15T10:22:55.747 回答