代码之家  ›  专栏  ›  技术社区  ›  Steve De Caux

普通SQL与方言

  •  3
  • Steve De Caux  · 技术社区  · 15 年前

    DBMS供应商使用SQL方言功能来区分其产品,同时声称支持SQL标准。纳夫说了这个。

    有没有您编码的SQL示例不能转换为SQL:2008标准SQL?

    具体来说,我讲的是DML(一个查询语句),而不是DDL、存储过程语法或任何不是纯SQL语句的东西。

    我还谈到了在生产中使用的查询,而不是特别的东西。

    编辑1月13日

    感谢您的所有回答:他们给我的印象是,创建了许多特定于DBMS的SQL,以便为糟糕的关系设计提供解决方案。这让我得出结论你可能不会 希望 移植大多数现有应用程序。

    5 回复  |  直到 15 年前
        1
  •  3
  •   ConcernedOfTunbridgeWells    15 年前

    典型的区别包括细微的不同语义(例如,在某些情况下,Oracle处理空值与其他SQL方言不同)、不同的异常处理机制、不同的类型和处理字符串操作、日期操作或层次查询等操作的专有方法。查询提示的语法在不同的平台上也有所不同,不同的乐观者可能会对不同类型的构造感到困惑。

    人们可以在大多数数据库系统中使用ANSISQL,并期望在数据库上获得合理的结果,而不存在诸如缺少索引之类的重大调整问题。然而,在任何不平凡的应用程序上,可能都需要一些代码,这些代码不容易移植。

    通常,这一需求将相当局限于应用程序代码库中——这会导致问题的少数查询。报告更可能引发这种类型的问题,并且跨数据库管理器执行通用的报告查询很难很好地工作。有些应用程序比其他应用程序更容易导致悲伤。

    因此,在一般情况下,不太可能依赖应用程序的“可移植”SQL构造。一个更好的策略是在通用语句的工作位置使用通用语句,并在数据库特定的层中突破通用语句。

    一种通用的查询机制可以在可能的情况下使用ANSI SQL;另一种可能的方法是使用O/R映射器,它可以为各种数据库平台获取驱动程序。这种类型的机制应该足以满足大多数数据库操作,但需要您在平台耗尽蒸汽的情况下执行一些特定的工作。

    您可以将存储过程用作更复杂操作的抽象层,并为每个目标平台编写一组特定于平台的存储过程。可以通过类似ado.net的方式访问存储过程。

    在实践中,参数传递和异常处理中的细微差异可能会导致此方法出现问题。更好的方法是生成一个封装 具有公共接口的特定于平台的数据库操作。根据您使用的DBMS平台,不同的“驱动程序”模块可以换入换出。

        2
  •  3
  •   thecoop    15 年前

    Oracle增加了一些功能,例如 model hierarchical 如果不是不可能的话,很难转换成纯SQL的查询

        3
  •  1
  •   slebetman    15 年前

    即使SQL:2008可以做一些事情,有时语法也不相同。以regexp匹配语法为例,sql:2008使用 LIKE_REGEX VS MySQL REGEXP .

    是的,我同意,这很烦人。

        4
  •  1
  •   Cylon Cat    15 年前

    Oracle的部分问题在于它仍然基于SQL1992-ANSI标准。SQL Server是基于SQL 1999标准的,所以一些看起来像“扩展”的东西实际上是较新的标准。(我相信“over”条款就是其中之一。)

    Oracle对在SQL中放置子查询也有更严格的限制。SQL Server在几乎任何地方都允许子查询方面更加灵活和宽容。

    SQL Server有一种合理的方法来选择结果的“top”行:“select top 1 from customers order by sales_total”。在Oracle中,这变为“select*from(select customers order by sales_total)”,其中row_number<=1。

    当然,总是有甲骨文的臭名昭著的选择(表达式)从双重。

    编辑添加:

    现在我在工作,可以访问我的一些示例,这里有一个很好的例子。这是由LinqToSQL生成的,但在排序后从表中选择第41行到第50行是一个干净的查询。它使用“over”子句:

    SELECT [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[Country], [t1].[Phone], [t1].[Fax]
        FROM (
            SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ContactName]) AS [ROW_NUMBER], [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
            FROM [dbo].[Customers] AS [t0]
            ) AS [t1]
        WHERE [t1].[ROW_NUMBER] BETWEEN 40 + 1 AND 40 + 10
        ORDER BY [t1].[ROW_NUMBER]
    
        5
  •  1
  •   Community Keith    7 年前

    在这里很常见,所以

    准确回答:

    根据我的 answer/comments 在这里