代码之家  ›  专栏  ›  技术社区  ›  Jim Ferrans

同时支持Oracle和MySQL:它们的SQL语法有多相似?

  •  5
  • Jim Ferrans  · 技术社区  · 16 年前

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

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

    细节:

    • 我们使用的是ibatis,它是一个持久性管理器,可以将SQL语句清晰地分隔成资源文件。但是我们在SQL级别工作,这有其优点(和缺点)。
    • 我们不希望移动到像Hibernate这样的对象关系映射器,它将完全保护我们不受方言差异的影响。
    • 我们已经尽力保留OracleSQL的通用子集。
    • 没有PL/SQL。
    • 我们不使用存储过程或触发器(无论如何)。
    • 我们使用检查约束、唯一约束和外键约束。
    • 我们使用删除级联。
    • 我们使用事务(在iBATIS API级别完成)。
    • 我们在查询中调用了一些Oracle时间戳函数。
    • 我们将使用innodb存储引擎和mysql(它支持事务和约束)。

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

    最后更新: 感谢所有的答案,尤其是特罗埃尔斯·阿尔文关于分歧的文章。令人遗憾的是,标准并不是更标准的。对于我们来说,问题是mysql的自动增量与Oracle序列的对比,mysql的限制与Oracle rowumber()的对比,以及奇数函数或两个。大多数其他东西都应该很容易传输,模块化一些编辑,以确保我们使用的是SQL-92,正如@mjv指出的那样。更大的问题是,有些查询可能需要在每个DBMS中进行不同的手工优化。

    5 回复  |  直到 16 年前
        1
  •  9
  •   mjv    16 年前

    在路上会有一些小的颠簸,但总的来说应该比较容易。

    从您当前使用的功能列表中,应该只存在一些同步策略或语义差异,通常易于修复或说明。不使用pl/sql和/或存储过程是一个优点。一个好的经验法则是尝试并坚持大多数DBMS支持的SQL-92,特别是Oracle和MySQL。(注意,这不是当前的SQL标准,即SQL-2008)。

    一些不同之处:

    • “limit”是一个著名的例子:为了限制结果列表中要检索的行数,mysql使用limit n,在查询结束时,oracle在where子句中使用rownumber()(这很痛苦,因为您还需要在select列表中引用它…)
    • 某些数据类型不同。我认为主要是布尔型(但是谁使用这个;-)还有一些我认为与日期时间类型/格式有细微差别。
    • 有些函数名不同(子字符串与子字符串等)

    刚刚发现了一个 good resource about differences between SQL implementations .

    阅读别人的回答,是的,DDL,可能是个问题。我不同意这一点,可能是因为许多应用程序不需要DDL,您只需要立即设置数据模式等,然后使用SQL查询、添加或更新数据。

        2
  •  7
  •   RRUZ    16 年前

    我相信,使用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)
    

    你可以查一下这个 Comparison of different SQL implementations

        3
  •  4
  •   O. Jones    16 年前

    除了其他人提到的内容之外,Oracle和MySQL处理外部连接的方式也大不相同。实际上,Oracle提供了MySQL无法处理的语法,但Oracle将处理标准语法。

    甲骨文:

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

    MySQL和Oracle:

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

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

        4
  •  3
  •   ChssPly76    16 年前

    你肯定不能保持你的DDL不变。就DML而言,有许多相似之处(每个数据库都支持ANSISQL标准的核心子集),但也有一些不同之处。

    首先,MySQL使用自动增量值,Oracle使用序列。可以解决这个问题(Oracle端的sequence+trigger来模拟自动增量),但它确实存在。内置功能非常不同。

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

        5
  •  2
  •   Gary Myers    16 年前

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