代码之家  ›  专栏  ›  技术社区  ›  Martin

参数化SQL列?

  •  8
  • Martin  · 技术社区  · 16 年前

    下面是一个示例,假设我有一个表,其中包含列名称、地址、电话。我有一个我跑步的网页 并将它们作为选项填充到“选择”下拉列表中。

    接下来,我有一个名为 搜索

    result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);
    

    但我从中得到一种讨厌的感觉。我使用参数化查询的原因是为了避免使用 逃跑 可能不是为转义列名而设计的。

    我怎样才能确保这是我想要的?

    编辑: 我之所以需要动态查询,是因为模式是用户可配置的,我不会去修复任何硬编码的东西。

    6 回复  |  直到 15 年前
        1
  •  6
  •   zigdon    16 年前

    与其传递列名,不如传递一个标识符,您可以使用硬编码表将该标识符编码为列名。这意味着您不必担心恶意数据被传递,因为所有数据要么是合法翻译的,要么是已知无效的。Psudoish代码:

    @columns = qw/Name Address Telephone/;
    if ($columns[$param]) {
      $query = "select * from contacts where $columns[$param] = ?";
    } else {
      die "Invalid column!";
    }
    
    run_sql($query, $search);
    
        2
  •  0
  •   harpo Binary Worrier    16 年前

    尽管如此,还是可以做到的,我建议使用一个单独且严格的函数来验证列名。允许它只接受一个标识符,比如

    /^\w[\w\d_]*$/
    

    您将不得不依赖于您对自己的列名所做的假设。

        3
  •  0
  •   Brad Osterloo    16 年前

        4
  •  0
  •   Turnkey    16 年前

    根据另一个查询的结果将列创建为一个表,该表枚举可能的架构值。在第二个查询中,您可以将select硬编码为用于定义架构的列名。如果未返回任何行,则输入的列无效。

        5
  •  0
  •   Jonathan Leffler    16 年前

    在标准SQL中,分隔标识符用双引号括起来。这意味着:

    SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?
    

    这本身并没有多大帮助,但是……如果您可以对通过web表单输入的名称应用带双引号的escape()技术,那么您就可以信心十足地构建查询。

    当然,您说过希望避免使用escape,实际上,您不必在提供参数的参数上使用它?席位持有者。但是,当您将用户提供的数据放入查询时,您需要保护自己免受恶意用户的攻击。

    不同的数据库管理系统提供分隔标识符的方式不同。例如,MS SQL Server似乎使用方括号[SomeTable]而不是双引号。

        6
  •  0
  •   runrig    16 年前

    某些数据库中的列名可能包含空格,这意味着您必须引用列名,但如果您的数据库不包含此类列,则只需通过正则表达式或某种检查运行列名,然后再拼接到SQL中:

    if ( $column !~ /^\w+$/ ) {
      die "Bad column name [$column]";
    }