【问题标题】:PHP Mysql - Use a variable as column name in Select statementPHP Mysql - 在 Select 语句中使用变量作为列名
【发布时间】:2014-09-05 15:50:15
【问题描述】:

我的表中有月份名称作为列名,例如 jan、feb、march 等。
在我的表单中,用户需要从下拉列表中选择一个月,我会选择用户的选择 作为 $month_name。

我想查看 $month_name 中不是 0.00 的数据。

当我回显 $month_name 时,我得到:jan 或 feb 等。

我在我的选择语句中使用了 $month_name 但不起作用:

第一次尝试不工作:

$sql = "SELECT * FROM bookoff_monthly WHERE '.$month_name.' <> 0.00 AND year='$year' ";

第二次尝试不工作:

$sql = "SELECT * FROM bookoff_monthly WHERE $month_name <> 0.00 AND year='$year' ";

** 但以下工作,但这不是我想要的:

$sql = "SELECT * FROM bookoff_monthly WHERE jan <> 0.00 AND year='$year' ";

【问题讨论】:

    标签: php mysql sql-server database


    【解决方案1】:

    这是我认为正确转义的:

    $sql = "SELECT * FROM bookoff_monthly WHERE `".$month_name."` <> 0.00 AND year='".$year."' ";
    

    请注意,在$month_name 周围,语句中有反引号,然后是双引号(因为整个查询都被它们包围),然后是PHP 连接(.)。您最好将其视为string + variable + string ...,而不是字符串中的变量。与 $year 变量相同。

    在您的第一个语句中,您很接近,但您使用单引号来分隔字符串,但如果字符串包含在双引号中,则不能这样做。

    $var = "is a";
    
    echo("This ".$var." string 'with quoted text'"); // This is a string 'with quoted text'
    
    echo("This ".$var." string \"with quoted text\""); // This is a string "with quoted text"
    
    echo('This '.$var.' string "with quoted text"'); // This is a string "with quoted text"
    
    echo('This '.$var.' string \'with quoted text\''); // This is a string 'with quoted text'
    

    假设您的变量格式正确,那么这应该可以工作。

    编辑:正如 VMai 所说,因为您处理的是 3 个字母的月份名称,所以您将不可避免地在此查询中使用“DEC”或“dec”,这是 MySQL 中的保留字,因此您必须 使用反引号转义名称,否则查询将被误解。

    【讨论】:

    • 您可以添加转义标识符在这种情况下是必须的,因为DEC 列会破坏未转义的查询。原因:DEC 是 MySQL 中的 reserved word。 $year 可以按原样使用,但最好使用参数化的预处理语句。请注意,不能使用参数作为标识符。
    • 说得好!出于这个原因,我总是将列名和表名包含在反引号中
    • 这也是正确的,但不在这个问题的范围内
    • 请注意,“引用”仍然没有被转义——查询仍然容易受到攻击。这仅在$month_name 被引用作为标识符 并且$year 被引用作为文字 时才有效。由于OP根本没有执行任何SQL保护,这个真的应该在答案中解决。
    • 同意反引号。不同意留下双引号。我会一直留在引号中,因为变量 ate 在双引号内解析,并且因为它更容易在没有连接符的情况下查看/阅读。 *被解析
    【解决方案2】:

    至于直接问题:

    #1 的问题是您试图混合使用单引号和双引号。假设 $month_name = "jan",这会给你:

    SELECT * FROM bookoff_monthly WHERE '.jan.' <> 0.00 AND year='$year'
    

    作为“.jan.”不等于 0.00,这不会找到任何记录。

    您的第二个在我看来应该可以工作。您可以尝试打印结果字符串,看看它给了您什么。或许您在 month_name 或其他内容中有您不希望出现的其他字符。

    但无论如何,这只是要求进行 SQL 注入攻击。例如,黑客可以伪造您的输入表单并设置 jan="1+1=2; delete from bookoff_monthly where 1.00 ",现在它将删除给定年份的所有内容。

    此外,任何让您动态生成字段名称的设计都应该立即受到质疑。

    执行此操作的正确方法是与每个月的一条记录建立多对五的关系。像创建表 bookoff_month (bookoff_id int, month char(3), amount decimal(7,2))。然后您的查询变为 select * from bookoff_monthly join bookoff_month on bookoff_month.bookoff_id=bookoff_monthly.bookoff_id where month=?和年=?并用准备好的语句填充它们,或者至少将参数包装在一个正确转义的函数中。

    【讨论】:

      【解决方案3】:

      $sql = 'SELECT * FROM bookoff_monthly WHERE '.$month_name.' &lt;&gt; 0.00 AND year="'.$year.'"

      【讨论】:

      • 这个答案虽然可能有效,但非常很糟糕。嵌入在查询中的标识符和文字都不受注入保护。
      猜你喜欢
      • 2014-08-12
      • 1970-01-01
      • 2015-01-27
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      • 1970-01-01
      • 1970-01-01
      • 2021-06-25
      相关资源
      最近更新 更多