【问题标题】:passing table and column name dynamically using bind variables使用绑定变量动态传递表和列名
【发布时间】:2012-04-01 05:00:56
【问题描述】:

有没有办法使用绑定变量将列名和表名动态传递给查询?这可以通过使用简单的串联运算符|| 来完成,但我想要一种不同的方法来实现这一点。

编辑

OPEN abc_cur FOR 'Select :column_name
                  from :table_name' 
                USING column_name,table_name;

在此示例中,我将 column_name 传递为 empno,ename 并将 table_name 传递为 emp

但是这种方法对我不起作用。除了传统的连接方法之外,是否有可能采用不同的方法?

【问题讨论】:

  • @Adrian:你明白我的意思吗?
  • 老实说,没有。我认为你应该详细说明。

标签: sql oracle plsql oracle11gr2


【解决方案1】:

表名和列名不能作为绑定变量传递,不。绑定变量的全部意义在于,Oracle 可以为语句生成一次查询计划,然后使用不同的绑定变量值执行多次。如果优化器不知道正在访问哪个表或正在选择和过滤哪些列,它就无法生成查询计划。

如果您担心 SQL 注入攻击,并假设动态 SQL 确实是必要的(大多数情况下,需要诉诸动态 SQL 意味着数据模型存在问题),您可以使用 DBMS_ASSERT package 来验证表名和列名不包含嵌入式 SQL。

【讨论】:

  • 我关心的是动态创建一个 sql 查询然后执行它。有什么替代方法吗?
  • @ Gaurav Soni- 你有什么顾虑?
  • 我可以用v_sql:=select '||column_name||' from dual where 1=1之类的字符串连接创建我的动态sql,然后再创建另一个这样的字符串,我们如何更有效地创建它,我的意思是除此之外的其他方法
  • :除此之外还有没有更优化的高效方法?
  • @Gaurav Soni-您是否担心字符串连接本身很慢?你正在做过多的硬解析?您正在为 SQL 注入攻击打开安全漏洞?或者是其他东西?大多数设计良好的系统都不需要求助于动态 SQL,所以我总是怀疑动态 SQL 被用来掩盖糟糕的设计。但是,如果您确实需要动态查询,则需要动态组合字符串。
【解决方案2】:

不,你不能。更改查询中的表或列名称会更改该查询的语义 - 即它变成一个不同的查询。

绑定变量都是关于将不同的值传递给 same 查询。优化器可以重用具有不同值的查询,而无需重新解析和优化它。

【讨论】:

    【解决方案3】:

    当我不得不根据<select> 元素的值更改查询中的表时,我遇到了类似的问题。在这里的大多数答案中都说表名不能作为绑定变量传递,但是当我创建一个包含表名并传递给我的 sql 查询的变量时,它实际上起作用了:

    <?php
    
    $conn = mysqli_connect("<host>", "<username>", "<password>", "<database>");
    
    $variable = "table_name";
    $sql = $conn->("SELECT <column_name> FROM $variable ....);
    
    ?>
    

    所以我所做的是我创建了一个函数并在我的函数中编写了我所有的 sql 查询。对于函数参数,我传递了名为 $table 的变量:

    function getResult($table){
        
    $conn = mysqli_connect("<host>", "<username>", "<password>", "<database>");
        $minDate = $conn->real_escape_string($_POST['minDate']);
        $maxDate = $conn->real_escape_string($_POST['maxDate']);
        $jobName = $conn->real_escape_string($_POST['jobName']);
    
    
    
    $sql = $conn->query("SELECT COUNT(countX) as boxCount FROM $table WHERE job_name='$jobName' AND dateX BETWEEN '$minDate' AND '$maxDate'");
    
    
    /* ... I removed the other operations from the code to make it compact */
    

    然后我编写了根据作业名称的值更改目标表的条件:

    if ($_POST['jobName'] === "job1"){
        getResult("table_name");
    }
    else if($_POST['jobName'] === "job2") {
        getResult("table_name");
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      相关资源
      最近更新 更多