5

这是一个非常开放的问题,但我认为它对 SQL 的可读性非常有益。

因此,您有一个 Java 程序,并且您正试图从中调用一个巨大的 SQL 语句,其中包含许多子查询和连接。我的问题的起点是这样的字符串常量:

static string MONSTER_STATEMENT = 
  "SELECT  " +
  "   fields" +
  "WHERE "+
  "   fieldA = (SELECT a FROM TableC) " +
  "AND fieldB IN (%s)" +
  "AND fieldC = %d " +
  "FROM "
  "   tableA INNER JOIN tableB ON ...";

它稍后会使用 String.format 填充并执行。

你有什么技巧可以让这种东西变得可读?你分开你的内部连接。您是否在字符串中缩进 SQL 本身?你把评论放在哪里?请分享您的武器库中的所有技巧。

4

3 回答 3

1

如果我使用像 Management Studio 这样的管理控制台直接查询数据库,我的倾向是格式化我的 SQL 语句。因此,当我构建 SQL 语句时,我会花时间在空格和换行符上。与能够读取 SQL 所节省的时间相比,消耗的额外空间是无关紧要的,我应该打印出来或使用 SQL Profiler 捕获它。所以,我会倾向于StringBuilder像这样组装我的 SQL:

StringBuilder sql = new StringBuilder();
sql.append("Select ....");
sql.append("\t\n, AdditionalCol, ...");
sql.append("\nFrom ...");
sql.append("\n  Inner Join ...");
sql.append("\n      On ColA =  ...");
sql.append("\nWhere Col1 = (");
sql.append("\n          Select a");
sql.append("\n          From TableC");
sql.append("\n          ");
sql.append("\n  And ColB In(%s)");
sql.append("\n  And ColC = %d");
于 2010-05-05T16:55:13.817 回答
1

围绕构建过程的辅助类可能会对您有所帮助。那可能是一个: http: //openhms.sourceforge.net/sqlbuilder/

无论如何,始终使用准备好的陈述。

于 2010-05-05T17:11:21.400 回答
0

如此复杂的 SQL 应该放在一个准备好的语句中,而不是放在一起,String.format以避免 SQL 注入问题。

我做以下两件事之一:将其包装在可调用语句中或将其放入 configuration/xml 文件中。Java 源文件不适合复杂的 SQL。

话虽如此,IDEA 有一个语言格式化功能,它可以将 Java 中的字符串格式化为一种不同的语言(基于它们传递给的方法或基于注释),因此可以提供帮助。

编辑:鉴于您的情况,我同意可调用语句可能不可行。准备好的语句仍然值得,即使对于内部开发,只是因为带有撇号的参数可以炸毁一切(即使没有攻击者),所以仍然值得,IMO,做额外的努力来创建字符串在代码中动态地(String.format 或其他任何内容)仅用于无法作为参数传递的部分(如您的示例中的临时表名),然后将其用作准备好的语句,为其余部分传递适当的参数。

至于让它不那么难看,它看起来像一个配置/xml类型的文件是我想要的。

于 2010-05-05T16:44:41.503 回答