【问题标题】:How to handle HUGE SQL strings in the source code如何处理源代码中的巨大 SQL 字符串
【发布时间】:2008-12-19 22:07:13
【问题描述】:

我目前正在做一个项目,其中代码中有大约 3000 行的 SQL 字符串。

该项目是一个java项目,但这个问题可能适用于任何语言。

无论如何,这是我第一次看到这么糟糕的事情。 代码库是遗留的,所以我们可以突然迁移到 Hibernate 或类似的东西。

你如何处理这样非常大的 SQL 字符串?

我知道这很糟糕,但我不知道最好的解决方案是什么。

【问题讨论】:

    标签: java sql coding-style


    【解决方案1】:

    在我看来,将这些硬编码的值放入存储过程并从代码中引用存储过程可能是高产出和低工作量。

    【讨论】:

    • 我看不出有任何理由不让它们成为存储过程。高产少努力是对的!
    • 你没有看到这个查询听起来很积极。 :) 你指的是什么硬编码值?
    【解决方案2】:

    SQL 是否有很多用于变量的字符串连接?

    如果没有,您可以提取它们并将它们放入资源文件中。但是您必须删除换行符中的字符串内容。

    您使用的存储过程方法非常好,但有时当需要了解 SQL 在做什么时,您必须从工作区切换到您喜欢的 SQL IDE。这是唯一的坏事。

    我的建议是这样的:

    String query = "select ......."+
    3000 lines.
    

    ResourceBundle bundle = ResourceBundle.getBundle("queries");
    String query = bundle.getString( "customerQuery" );
    

    就是这样。

    【讨论】:

    • 我喜欢这个,我现在正在实施这个!
    【解决方案3】:

    我想第一个问题是,你应该用它做什么?如果它没有坏,就悄悄地把它合上,假装你从未见过它。否则,像疯了一样重构——希望某处有一些类似于合同的退出条件。

    【讨论】:

    • 不幸的是它坏了。或者更确切地说,它已更改,现在不符合代码质量标准。
    • 然后从java中取出,放入一个SP中。这不是分解它,而是将它从不合适的地方移动到合适的地方,因为它不会修复损坏的东西,但可能会更改代码标准规则。 (无论如何都应该移动。)
    • 那你要发的话,我帮忙看看能不能补一下。
    • -1 因为这是一个不专业的答案。是的,逃避问题和遗留代码很容易,但在 StackOverflow,我希望找到实际的技巧和解决方案,而不是像“假装你从未见过”这样的愚蠢答案。但我欣赏幽默感。真的。
    【解决方案4】:

    到目前为止,我能想到的最好的办法是将查询放入多个存储过程中,就像我在 Java 中处理过长的方法一样。

    【讨论】:

    • 几个存储过程?这是一个大查询还是这到底是什么?
    • 绝对有。最大的问题是它难以理解。
    • 长长的 sql 语句本身并没有什么坏处。如果您将它们分解并取部分之和,则理解它们并不容易。而且这种方式可能更有效。有什么方法可以知道它是否经过分析/优化?
    • 分解是一个不可转移的概念,从过程代码(几乎总是胜利)到声明性代码(几乎总是失败)。这就是临时表是 SQL 反模式的原因。
    • 分解在 SQL 中绝对有效。您可以拆分具有多个连接的复杂查询,并使用视图或存储过程使其易于理解。
    【解决方案5】:

    我和你在同一个地方...我的计划是将 SQL 提取到项目中的单独 .sql 文件中,并创建一个实用方法来在我需要查询时读取文件。

    string sql = "select asd,asdf,ads,asdf,asdf," 
               + "from asdfj asfj as fasdkfjl asf"
               + "..........................."
               + "where user = @user and ........";
    

    查询被转储到一个名为usageReportByUser.sql的文件中
    然后变成这样。

    string sql = util.queries("usageReportByUser");
    

    确保以不公开访问文件的方式完成。

    【讨论】:

    • 您可以使用 ResourceBundle 非常轻松地加载 sql。这很简单。然后使用 Velocity 之类的东西替换变量。
    【解决方案6】:

    使用框架iBatis

    【讨论】:

      【解决方案7】:

      我为此写了一个toolkit,并在几个项目中使用了它。它允许您将查询放在大部分文本文件中,并为它们生成绑定和文档。

      查看this exampleexample use(它几乎只是一个编译成具有早期绑定/类型安全查询绑定的java 类的准备好的语句)。

      它也会生成一些不错的 javadocs,但我目前没有在线文档。

      【讨论】:

        【解决方案8】:

        我赞同 iBatis 的建议。至少,您可以从最可能使用 StringBuffer 的 Java 代码中提取 SQL,并将其附加或 String concat 到 XML 中,这样更易​​于维护。

        我为旧版 Web 应用程序执行此操作,然后打开调试并为 DAO 运行单元测试,并将为每个语句生成的 sql 复制到 iBatis xml 中。工作很顺利。

        【讨论】:

          【解决方案9】:

          我在 PHP 中所做的是:

          $query = "SELECT * FROM table WHERE ";
          $query .= "condition < 5 AND ";
          $query .= "condition2 > 10 AND ";
          

          然后,一旦你在 $query 上完成分层:

          mysql_query($query);
          

          【讨论】:

            【解决方案10】:

            一种简单的方法是将它们分解为某种常量。这至少会使代码更具可读性。

            【讨论】:

              【解决方案11】:

              我将它们存储在文件(或资源)中,然后在应用启动时读取并缓存它们(如果它是服务或其他东西,则在更改时)。

              或者,只需将它们作为 consts 或 readonlys 放入一个大的旧 SqlQueries 类中。

              【讨论】:

                【解决方案12】:

                我已经成功地将大型动态查询转换为 linq 查询。 (1K 行+)这非常适用于在相对较少的表格上进行大量动态过滤和动态分组的报告方案。为这些表创建一个 edmx,您可以编写出色的强类型可组合查询。

                我发现性能实际上得到了提高,生成的 sql 也简单了很多。 我敢肯定你会用 Hibernate 获得类似的里程 - 除了能够使用 linq 当然。但一般来说,如果生成的 sql 需要高度动态,那么它不适合存储过程。在存储过程中编写动态 sql 是两全其美的。 sql 生成框架将是我去这里的首选方式。如果您挖掘 Hibernate,我认为这将是一个很好的解决方案。

                话虽如此,如果查询只是带有参数的简单字符串,那么只需将它们放入存储过程中即可完成。 - 但是你错过了与对象一起工作的结果。

                【讨论】:

                  猜你喜欢
                  • 2011-08-31
                  • 2010-09-06
                  • 2010-09-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-12
                  相关资源
                  最近更新 更多