【问题标题】:Is it possible to refer to column names via bind variables in Oracle?是否可以通过 Oracle 中的绑定变量引用列名?
【发布时间】:2009-03-04 10:42:16
【问题描述】:

我试图在与 Oracle 数据库通信的应用程序中引用列名来排序查询。我想使用绑定变量,以便我可以动态更改查询的顺序。

我遇到的问题是数据库似乎忽略了按列排序。

有谁知道是否有通过绑定变量引用数据库列的特定方法,或者是否有可能?

例如我的查询是

SELECT * FROM PERSON ORDER BY :1

(其中:1 将绑定到PERSON.NAME) 查询未按字母顺序返回结果,我担心数据库将其解释为:-

SELECT * FROM PERSON ORDER BY 'PERSON.NAME' 

这显然行不通。

非常感谢任何建议。

【问题讨论】:

    标签: oracle data-binding jdbc sql-order-by


    【解决方案1】:

    没有。您不能将绑定变量用于表名或列名。

    创建执行计划需要此信息。例如,如果不知道要按什么排序,就不可能弄清楚要使用什么索引。

    当您的程序创建列名时,您必须直接将列名插入到 SQL 语句中,而不是绑定变量。假设您对 SQL 注入采取了预防措施,则没有任何不利之处。

    更新:如果你真的想跳槽,你可以做类似的事情

    order by decode(?, 'colA', colA, 'colB', colB)
    

    但这只是愚蠢的。而且慢。不要。

    【讨论】:

    • +1 顺便说一句,我不知道这是否适用于 Oracle,但在其他数据库(如 DB2)中肯定存在缺点 - 如果您修改数据库缓存查询会变得更加困难一直查询命令文本(而不仅仅是参数的值)
    • 这也发生在 oracle 中。但是您不会一直更改命令文本。列名只有几个选择,所以缓存条目也就五个左右。
    • 非常感谢,这对我来说很有意义。我将尝试让代码在查看 order by 子句时理解它,如果它包含绑定变量,我将用它的值替换它。
    • 嗯...你不能一开始就不绑定它吗?它仍然可以是程序中的参数。在编写完 SQL 语句后尝试修复它听起来很棘手。
    • 并非如此 - 构建查询的工具会解析占位符的 sql 字符串,然后用占位符的值填充占位符。这意味着在某些时候我肯定会不得不返回并弄乱声明以放置列名而不是尝试绑定它们。
    【解决方案2】:

    当您使用 JDBC 时。您可以将代码重写为没有绑定变量的内容。这样,您还可以动态更改 order-by,例如:

    String query = "SELECT * FROM PERS ";
    if (condition1){
      query = query+ " order by name ";
    // insert more if/else or case statements
    } else {
      query = query+ " order by other_column ";
    }
    Statement select = conn.createStatement();
    ResultSet result = select.executeQuery(query);
    

    甚至:

    String columnName = getColumnName(input);
    Statement select = conn.createStatement();
    ResultSet result = select.executeQuery("SELECT * FROM PERS ORDER BY "+columnName);
    

    【讨论】:

    • SQL 最好留在数据库中。
    • 我不同意 - 这是一个很好的建议 Edwin,谢谢。看起来我可能不得不做这样的事情。当我按列添加顺序时,我还需要从查询字符串中删除一些占位符。
    【解决方案3】:
    ResultSet result = select.executeQuery(
        "SELECT * FROM PERS ORDER BY " + columnName
    );
    

    将始终是数据库的语句。
    这意味着,就像 Thilo 已经解释的那样,不可能“重新排序”已经绑定、计算、准备、解析的语句。在您的应用程序中一遍又一遍地使用此结果集时,唯一会随时间变化的是演示文稿的顺序,请尝试在您的客户端代码中对结果集进行排序。
    否则,动态 SQL 也可以,但会占用大量资源。

    【讨论】:

    • 只有当 columnName always 不同时,它才会是一个新语句。我希望 columnName 只取一小组值中的一个,这意味着对共享池的损害将是最小的。
    猜你喜欢
    • 2019-08-23
    • 2021-01-26
    • 2015-06-07
    • 2014-07-20
    • 2014-12-19
    • 2019-08-18
    • 2021-10-06
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多