这个连接语句有什么问题?

问题描述 投票:1回答:3

我正在使用MySQL服务器Server version: 5.6.42-cll-lve - MySQL Community Server (GPL),我遇到了一些与CONCAT()的主要问题

       public function get_urls() {
        // Create query
        $query = "SELECT a.Name, a.PrimaryVersion, e1.URL
        FROM " . $this->table . " a
        INNER JOIN
        FunnelsFlows b ON a.Funnel_ID = b.Funnel_ID
        INNER JOIN
        BackendFlows c ON b.BackendFlow_ID = c.BackendFlow_ID
        INNER JOIN
        BackendLevels d ON CONCAT(c.Level, :lv) = d.BackendLevel_ID
        LEFT JOIN
        BackendPages e1 ON d.Upsell = e1.BackendPage_ID
        LEFT JOIN
        BackendPages e2 ON d.Downsell1 = e2.BackendPage_ID
        LEFT JOIN
        BackendPages e3 ON d.Downsell2 = e3.BackendPage_ID
        WHERE                    
        a.Funnel_ID = :fid 
        LIMIT 0,1";
        // Prepare statement
        $stmt = $this->conn->prepare($query);
        // Bind ID
        $stmt->bindParam(':fid', $this->fid, PDO::PARAM_INT);
        $stmt->bindValue(':lv', $this->lv, PDO::PARAM_STR);
        // Execute query
        $stmt->execute();

运行此代码会引发以下错误:PHP Fatal error: Uncaught PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'c.Level' in 'on clause' in ...

您可以在此处查看整个数据库结构: https://app.sqldbm.com/MySQL/Share/wBAF2JMRFFSoPPjIPdYZc0GFrngIE8md_DYjF4jNYw0

php mysql pdo prepared-statement
3个回答
0
投票

您的查询不能像那样工作。您正在尝试使用参数CONCAT(c.Level, :lv)连接字段内容:lv。如果有一个列Level,这会产生一个字符串。但是,您更愿意构建像Level1 / Level2 aso这样的动态列名。

不幸的是,这不能通过参数来完成。这是因为查询计划已经准备好了。在执行时更改列名将改变查询计划。

您需要在这种情况下构建动态SQL或编写复杂的ON子句。

ON条款:

ON 
(
  (:lv = 1 AND c.Level1 = d.BackendLevel_ID)
  OR
  (:lv = 2 AND c.Level2 = d.BackendLevel_ID)
  -- and so on
)

动态SQL:

$sql = 'ON (c.Level' . inval($this->lv) . ' = d.BackendLevel_ID)'

由于PHP的intval函数被认为是安全的,我更倾向于后一个例子以提高SQL性能。


1
投票

删除引号(列名和值):

CONCAT(a.Level, :level)

此外,您使用错误的参数名称:

$stmt->bindParam(':level', $this->lv, PDO::PARAM_INT);
//                 ^^^^^

-1
投票

那这个呢?

$query = "SELECT a.Name, b.URL
        FROM " . $this->table . " a
        INNER JOIN
        FunnelsFlows b ON CONCAT(a.Level, ':lv') = b.Level_ID
        WHERE                
        a.Funnel_ID = :fid 
        LIMIT 0,1";
        // Prepare statement
        $stmt = $this->conn->prepare($query);
        // Bind ID
        $stmt->bindParam(':fid', $this->fid, PDO::PARAM_INT);
        $stmt->bindParam(':lv', $this->lv, PDO::PARAM_INT);
        // Execute query
        $stmt->execute();

这是一个快速反应,所以我现在解释一下。

我看到你想要将表列与字符串连接起来,对吗?

首先你有一个错误的标识:level,你试图用以下语句$stmt->bindParam(':lv', $this->lv, PDO::PARAM_INT);绑定,所以你必须用:lv更改它或将绑定语句变为$stmt->bindParam(':level', $this->lv, PDO::PARAM_INT);

第二 - 当你试图连接一个列时,你必须删除引号,所以它应该是CONCAT('a.Level',,如果第二个运算符是一个字符串,它应该是单引号,所以完整的CONCAT运算符应该写成如下CONCAT(a.Level, ':lv')

© www.soinside.com 2019 - 2024. All rights reserved.