8

让我在 OO 语言中使用 SQL 感到恼火的一件事是必须在字符串中定义 SQL 语句。

当我在 IBM 大型机上工作时,这些语言使用 SQL 预处理器从本机代码中解析 SQL 语句,因此这些语句可以用明文 SQL 编写,而无需对字符串进行混淆,例如在 Cobol 中有一个EXEC SQL 。 ... END-EXEC语法结构,允许将纯 SQL 语句嵌入到 Cobol 代码中。

<pure cobol code, including assignment of value
 to local variable HOSTVARIABLE>    

EXEC SQL
       SELECT COL_A, COL_B, COL_C
       INTO :COLA, :COLB, :COLC
       FROM TAB_A
       WHERE COL_D = :HOSTVARIABLE
END_EXEC

<more cobol code, variables COLA, COLB, COLC have been set>

...这使得 SQL 语句非常容易阅读和检查错误。在EXEC SQL .... END-EXEC标记之间没有缩进、换行等限制,因此您可以根据喜好格式化 SQL 语句。

请注意,此示例适用于单行选择,当需要多行结果集时,编码是不同的(但仍然易于阅读)。

所以,以Java为例

  1. 是什么让“旧 COBOL”方法不受欢迎?不仅是 SQL,而且系统调用也可以通过这种方法变得更具可读性。我们称之为嵌入式外语预处理器方法。

  2. 用于 SQL的嵌入式外语预处理器是否有用?您会看到能够在 java 代码中编写本机 SQL 语句的好处吗?

编辑

我真的在问您是否认为 OO 语言中的 SQL 是一种倒退,如果不是,那么可以做些什么来使它变得更好。

4

7 回答 7

4

Java 中已经有一个嵌入式 SQL 标准,称为SQLJ

话虽如此,我从未见过它在野外使用过,而且我不知道它是否真的是一种选择,使用现代工具。当标准出现时,甲骨文大力支持它,但我认为它已经死了。

于 2010-01-08T08:57:03.030 回答
2

SQL 域中已经有类似于 Java 和 .NET 的“嵌入式语言预处理器”的东西:http: //ibatis.apache.org/

此外,人们通常会使用成熟的 ORM,比如Hibernate来抽象出 SQL。

请注意,这些工具不允许将 SQL 字符串存储在 Java 代码本身中,但具有类似的目的。我个人认为将 SQL 字符串存储在代码本身中没有任何好处,因为这通常更混乱。将所有 SQL 整齐地写入特定文件有助于 SQL 的可重用性和可维护性。如果需要,它们确实允许将 SQL 作为字符串,但这通常是最后的手段(当 ORM 工具对您的用例没有很好的抽象时。)

编辑:我确实认为混合 SQL 和代码(无论是否是 OO)是脆弱的并且不可取。有一个集中的地方来存储您的查询要好得多。这就是 iBATIS 方法。

于 2010-01-08T08:58:03.510 回答
1

对象-关系映射工具,例如 Hibernate,理论上可以减少这类问题。“理论上”;)

另外,如果您可以使用 Grails,我听说您可以编写出色的多行字符串,这使得阅读 SQL 语句更容易。

于 2010-01-08T08:57:53.937 回答
1

对于目前的情况,我可以提供以下几点

  • 如上所述,java 中有一种技术可以做到这一点:SQLJ从未采用过。
  • 通常使用 ORM 来获得类似的结果(iBatisHibernate是我最关心的
  • C# 有 LINQ,它做类似的事情

将 sql 作为语言的一部分嵌入有很多问题:

  • 它倾向于将您的语言与数据库供应商联系起来,因为各种 sql 方言非常不同。对于大多数现代语言来说,这是不行的。这对 COBOL 来说不是问题,因为可移植性不是必需的。
  • 它使语言方式更复杂或需要预处理,两者本身都是坏事。但是对于现代 IDE,情况更糟,因为他们很难在代码中处理 sql(尽管他们开始实际这样做,即使 sql 嵌入在字符串中)。这对 COBOL 来说不是问题,因为从现代意义上讲,它无论如何都是一种丑陋的语言(尽管它在发明时可能很好)
  • 它需要难以控制的编译资源(即数据库)并遵循与“正常”编程完全不同的方法。再次,COBOL 程序和它的数据库几乎融合在一起,所以那里没有问题。
  • SQL 不适合 OO 范式。它返回值的二维数组,而不是对象。所以无论如何你都需要某种ORM。

另一方面,DSL 现在都是炒作。并且有些语言具有 XML 文字。因此,我认为很有可能出现(或已经存在)其中嵌入了类似 ORM 的功能并允许您在代码中使用 SQL(或 HQL?)之类的 DSL 的语言。

于 2010-01-08T09:51:22.897 回答
1

您可以使用体面的 IDE 解决这种无能为力的问题。例如,IntelliJ IDEA 支持一种称为注入语言的功能。它允许您在字符串文字中以您想要的语言编写代码,并能够使用代码突出显示、完成、导航和其他服务。您可以在此处阅读更多相关信息:http: //blogs.jetbrains.com/idea/2009/03/user-defined-language-injection/

于 2010-01-16T21:30:31.530 回答
0

像SQLJ这样的方法的主要缺点之一是预处理器会阻止将现代 IDE 工具用于数据访问逻辑这一事实。对于EclipseNetBeansIntelliJ IDEA等优秀的 IDE ,这是反对预处理器的有力论据(我们也在博客中对此进行了描述)。

与此同时,像Eclipse XtextJetBrains MPS这样的 DSL 工具仍在努力增强 Java 语言本身,以便拥有像您以前在 COBOL 中所拥有的东西。

一种选择是使用像jOOQ这样的内部 DSL来完成这项工作,尽管这并不是真正的 SQL

于 2014-04-05T16:23:38.037 回答
-2

好吧,最简单、最费脑筋的方法就是将您的 SQL 作为字符串包含在您的代码中。

就像是

   Statement s = new Statement("Select * from wherever");

这可能不是很复杂,但它确实有效。缺点是编译器无法检查您的 SQL 语法。稍微好一点的解决方案是Prepaired Statements,您可以在其中指定参数模板。因此,您可以执行以下操作:

PreparedStatement s = connection.prepareStatement("Select * from wherever where state = ?");

这样,当您在运行时创建准备好的语句时,您的 JDBC 连接应该立即抛出异常。因此,如果代码第一次工作,它应该总是工作。

然后在您的代码中稍后当您想要更改您所做的参数时:

s.setString(1, "CA");

Microsoft 有一个用于 .net 的嵌入式查询语言,称为LINQ。对于数据库,您可以使用LINQ to SQL,它可以让您在代码中直接嵌入查询。

于 2010-01-08T09:10:37.353 回答