doupo1908 2014-09-04 17:15
浏览 39
已采纳

准备语句使用int表字段进行插入

I am working a personal project to learn OOP. I created this generic method to do an insert to a table, but I could not. $dbAttributes is a list of fields in the table without the id. I pass an object instance, for example, product with properties set such as category_id,product_name, price. The problem comes when I try to bind the values using foreach loop.

I get errors:

SQLSTATE[HY000]: General error: 1366 Incorrect integer value

then after I removed single quote from the placeholder I get:

SQLSTATE[42000]: Syntax error or access violation: 1064

public static function create($obj) {
    global $db;

    $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $dbAttributes = $obj->db_fields;
    $colonValues = array();

    for($i=0;$i<count(array_values($dbAttributes));$i++){
        $colonValues[] = ':'.$dbAttributes[$i];
}

   $sql ="INSERT INTO ".$obj::$tableName."(";
   $sql .=join(",", array_values($dbAttributes));
   $sql .= ") VALUES('";
   $sql .= join("','",array_values($colonValues));
   $sql .= "')";

   try {
        $stmt = $db->prepare($sql);

        foreach($colonValues as $k=>$value){

            $rs = $obj->$dbAttributes[$k];
            //if($k!=0){
            $stmt->bindParam($value, $rs); 
            echo gettype($rs)." ". $rs."<br>";//}

    }

    var_dump($sql);
    $numRowsAffected = $db->exec($sql);

   } catch (Exception $ex) {
      echo $ex->getMessage();
   }

}

As you see I am trying to dynamically create SQL and also dynamically bind values. I tried everything and I also read the forum on using back-ticks for table names, it did not solve the problem.

  • 写回答

1条回答 默认 最新

  • dousong5161 2014-09-04 17:36
    关注

    You prepare the statement, but you don't execute the prepared statement. You exec($sql) as a non-prepared statement. This method doesn't support query parameters, it executes the SQL verbatim. So it's not surprising that MySQL complains when it expects an integer literal and finds :columnname.

    $numRowsAffected = $db->exec($sql);
    

    This should be:

    $stmt->execute();
    $numRowsAffected = $stmt->rowCount();
    

    Parameter placeholders must not go inside quotes in SQL.

    Also, you don't have to use bindValue(), you can just pass an array to execute().

    Here's a simpler way of writing your function:

    public static function create($obj) {
        global $db;
    
        $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
        $dbAttributes = $obj->db_fields;
        $columns = array_map(function ($col) { return "`" . $col . "`"; },
            array_values($dbAttributes));
        $paramPlaceholders = array_map(function ($col) { return ":" . $col; },
            array_values($dbAttributes));
        $paramValues = array_intersect_key(get_object_vars($obj), array_flip($dbAttributes));
    
        $sql ="INSERT INTO `".$obj::$tableName."` (".implode(",",$columns).")"
            . " VALUES (".implode(",",$paramPlaceholders).")";
    
        try {
            $stmt = $db->prepare($sql);
            $stmt->execute($paramValues);
            $numRowsAffected = $stmt->rowCount();
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动