Php 使用PDO准备语句将空变量插入MySQL

Php 使用PDO准备语句将空变量插入MySQL,php,mysql,pdo,Php,Mysql,Pdo,我的头撞在墙上,试图弄明白为什么PDO准备的声明不起作用。我唯一能得出的结论是,如果一个变量为空,则插入失败,但这令人困惑,因为我以前肯定做过一千次,没有问题 这是我的密码。所有变量都是通过POST变量设置的,因此如果用户不提供此数据,其中一些变量可能为空 $stmt = $db->prepare("INSERT INTO students (id, classid, userid, firstname, surname, form, gender) VALUES ('',

我的头撞在墙上,试图弄明白为什么PDO准备的声明不起作用。我唯一能得出的结论是,如果一个变量为空,则插入失败,但这令人困惑,因为我以前肯定做过一千次,没有问题

这是我的密码。所有变量都是通过POST变量设置的,因此如果用户不提供此数据,其中一些变量可能为空

$stmt = $db->prepare("INSERT INTO students
    (id, classid, userid, firstname, surname, form, gender)
    VALUES ('', :classid, :userid, :firstname, :surname, :form, :gender)");

    $stmt->execute(array(':userid' => $userid, ':classid' => $classid, ':firstname' => $firstname, ':surname' => $surname, ':form' => $form, ':gender' => $gender));
如果变量为空,是否有方法告诉它插入一个空字段

编辑:明确地说,这不是一个新的语句。我之前一直在使用毫无准备的MySQLi进行插入,只是刚刚开始将这段代码更新为PDO

编辑2:我的模式:

id  int(11) NO  PRI     auto_increment  
encryption  int(1)  NO              
classid int(11) NO              
googleclassroom varchar(50) NO              
userid  varchar(50) NO              
firstname   varchar(100)    NO              
surname varchar(100)    NO              
form    varchar(10) NO              
gender  varchar(10) NO              
colour_code varchar(10) NO              
col1    varchar(50) NO              
col2    varchar(50) NO              
col3    varchar(50) NO              
col4    varchar(50) NO              
col5    varchar(50) NO              
col6    varchar(50) NO              
col7    varchar(50) NO              
timestamp   datetime    NO  

您可以通过以下方式进行检查:

  • 允许所有列接受
    NULL
  • 如果
    id
    是主键,请将其从查询中删除。您可以将其设置为
    AUTO_INCREMENT
  • 编辑:

    由于
    id
    是架构中的主键,因此无法设置“”。此外,似乎不允许每个列都接受
    NULL
    ,因为用户没有提供值,
    $form
    之类的变量可能未定义或为NULL,所以INSERT语句将不会执行

    编辑2:

    试着找出确切的错误。不管是SQL还是PHP


    您可以使用

    设置显示错误。您可以通过以下方式进行检查:

  • 允许所有列接受
    NULL
  • 如果
    id
    是主键,请将其从查询中删除。您可以将其设置为
    AUTO_INCREMENT
  • 编辑:

    由于
    id
    是架构中的主键,因此无法设置“”。此外,似乎不允许每个列都接受
    NULL
    ,因为用户没有提供值,
    $form
    之类的变量可能未定义或为NULL,所以INSERT语句将不会执行

    编辑2:

    试着找出确切的错误。不管是SQL还是PHP


    您可以使用

    设置显示错误。我认为您遇到的问题是由于数据被绑定为
    bindParam()
    。根据PHP文档

    将PHP变量绑定到相应的命名或问号 SQL语句中的占位符,用于准备 声明

    因此我建议使用
    bindValue()
    。来解释为什么我要回到PHP手册

    与PDOStatement::bindValue()不同,变量被绑定为引用 并且将仅在执行PDOStatement::execute()时进行计算 打电话来

    所以我的答案是

    $stmt = $db->prepare("INSERT INTO students
        (classid, userid, firstname, surname, form, gender)
        VALUES (:classid, :userid, :firstname, :surname, :form, :gender)");
    
    $stmt->bindValue(':classid',$classid);//If this is a must enter or not entered by user then you can use bindParam()
    $stmt->bindValue(':userid',$userid);//This as well if this is a must enter then you can use bindParam()
    if($firstname == "" || $firstname == NULL){
    $stmt->bindValue(':firstname', NULL, PDO::PARAM_INT);//_NULL seems to give issues
    }else{
    $stmt->bindParam(':firstname', $firstname);
    }
    $stmt->bindValue(':surname',$surname);
    $stmt->bindValue(':form',$form);
    $stmt->bindValue(':gender',$gender);
    
    $stmt->execute();
    

    我认为您遇到的问题是由于数据被绑定为
    bindParam()
    。根据PHP文档

    将PHP变量绑定到相应的命名或问号 SQL语句中的占位符,用于准备 声明

    因此我建议使用
    bindValue()
    。来解释为什么我要回到PHP手册

    与PDOStatement::bindValue()不同,变量被绑定为引用 并且将仅在执行PDOStatement::execute()时进行计算 打电话来

    所以我的答案是

    $stmt = $db->prepare("INSERT INTO students
        (classid, userid, firstname, surname, form, gender)
        VALUES (:classid, :userid, :firstname, :surname, :form, :gender)");
    
    $stmt->bindValue(':classid',$classid);//If this is a must enter or not entered by user then you can use bindParam()
    $stmt->bindValue(':userid',$userid);//This as well if this is a must enter then you can use bindParam()
    if($firstname == "" || $firstname == NULL){
    $stmt->bindValue(':firstname', NULL, PDO::PARAM_INT);//_NULL seems to give issues
    }else{
    $stmt->bindParam(':firstname', $firstname);
    }
    $stmt->bindValue(':surname',$surname);
    $stmt->bindValue(':form',$form);
    $stmt->bindValue(':gender',$gender);
    
    $stmt->execute();
    

    罗布,这不是你问题的答案!我阅读了您的评论,我只是想向您展示如何正确使用错误报告、准备好的语句和异常处理

    如果愿意,可以用OOP或过程函数构造代码。但这一结构与此无关

    我的建议是:务必阅读您正在使用的函数的文档。尤其是返回的值。通过这种方式,您将知道如何正确处理所有可能的易出错情况。就PDO而言,这是一个强制性步骤;-)

    祝你好运

    <?php
    
    /*
     * Set error reporting level and display the errors on screen.
     * --------------------------------------------------------------
     * DON'T DISPLAY ERRORS ON PRODUCTION, DO IT ONLY ON DEVELOPMENT!
     * --------------------------------------------------------------
     */
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    
    try {
        /*
         * Create a PDO instance as db connection.
         */
    
        // Create PDO instance.
        $connection = new PDO(
                'mysql:host=localhost;port=3306;dbname=yourDb;charset=utf8'
                , 'yourDbUsername'
                , 'yourDbPassword'
        );
    
        // Assign driver options.
        $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
        $connection->setAttribute(PDO::ATTR_PERSISTENT, TRUE);
    
        /*
         * Prepare and validate the sql statement.
         * 
         * --------------------------------------------------------------------------------
         * If the database server cannot successfully prepare the statement, PDO::prepare() 
         * returns FALSE or emits PDOException (depending on error handling settings).
         * --------------------------------------------------------------------------------
         */
        $sql = 'INSERT INTO students (
                    classid,
                    userid,
                    firstname,
                    surname,
                    form,
                    gender
                ) VALUES (
                    :classid,
                    :userid,
                    :firstname,
                    :surname,
                    :form,
                    :gender
                )';
    
        $statement = $connection->prepare($sql);
    
        if (!$statement) {
            throw new UnexpectedValueException('The sql statement could not be prepared!');
        }
    
        /*
         * Bind the input parameters to the prepared statement.
         * 
         * -----------------------------------------------------------------------------------
         * Unlike PDOStatement::bindValue(), when using PDOStatement::bindParam() the variable 
         * is bound as a reference and will only be evaluated at the time that 
         * PDOStatement::execute() is called.
         * -----------------------------------------------------------------------------------
         */
    
        $bindings = array(
            ':classid' => $classid,
            ':userid' => $userid,
            ':firstname' => $firstname,
            ':surname' => $surname,
            ':form' => $form,
            ':gender' => $gender,
        );
    
        foreach ($bindings as $key => $value) {
            $bound = $statement->bindValue(
                    getInputParameterName($key)
                    , $value
                    , getInputParameterDataType($value)
            );
    
            if (!$bound) {
                throw new UnexpectedValueException('An input parameter could not be bound!');
            }
        }
    
        /*
         * Execute the prepared statement.
         * 
         * ------------------------------------------------------------------
         * PDOStatement::execute returns TRUE on success or FALSE on failure.
         * ------------------------------------------------------------------
         */
        $executed = $statement->execute();
    
        if (!$executed) {
            throw new UnexpectedValueException('The prepared statement could not be executed!');
        }
    
        /*
         * Get last insert id.
         */
        $lastInsertId = $connection->lastInsertId();
    
        if (!isset($lastInsertId)) {
            throw new UnexpectedValueException('The last insert id could not be read!');
        }
    
        /*
         * Close connection.
         */
        $connection = NULL;
    
        /*
         * Print results.
         */
        echo 'Provided data successfully added with the id: ' . $lastInsertId;
    } catch (PDOException $pdoException) {
        echo $pdoException->getMessage();
        exit();
    } catch (Exception $exception) {
        echo $exception->getMessage();
        exit();
    }
    
    /**
     * Get the name of an input parameter by its key in the bindings array.
     *  
     * @param int|string $key The key of the input parameter in the bindings array.
     * @return int|string The name of the input parameter.
     */
    function getInputParameterName($key) {
        return is_int($key) ? ($key + 1) : (':' . ltrim($key, ':'));
    }
    
    /**
     * Get the PDO::PARAM_* constant, e.g the data type of an input parameter, by its value.
     *  
     * @param mixed $value Value of the input parameter.
     * @return int The PDO::PARAM_* constant.
     */
    function getInputParameterDataType($value) {
        $dataType = PDO::PARAM_STR;
        if (is_int($value)) {
            $dataType = PDO::PARAM_INT;
        } elseif (is_bool($value)) {
            $dataType = PDO::PARAM_BOOL;
        }
        return $dataType;
    }
    

    罗布,这不是你问题的答案!我阅读了您的评论,我只是想向您展示如何正确使用错误报告、准备好的语句和异常处理

    如果愿意,可以用OOP或过程函数构造代码。但这一结构与此无关

    我的建议是:务必阅读您正在使用的函数的文档。尤其是返回的值。通过这种方式,您将知道如何正确处理所有可能的易出错情况。就PDO而言,这是一个强制性步骤;-)

    祝你好运

    <?php
    
    /*
     * Set error reporting level and display the errors on screen.
     * --------------------------------------------------------------
     * DON'T DISPLAY ERRORS ON PRODUCTION, DO IT ONLY ON DEVELOPMENT!
     * --------------------------------------------------------------
     */
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    
    try {
        /*
         * Create a PDO instance as db connection.
         */
    
        // Create PDO instance.
        $connection = new PDO(
                'mysql:host=localhost;port=3306;dbname=yourDb;charset=utf8'
                , 'yourDbUsername'
                , 'yourDbPassword'
        );
    
        // Assign driver options.
        $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
        $connection->setAttribute(PDO::ATTR_PERSISTENT, TRUE);
    
        /*
         * Prepare and validate the sql statement.
         * 
         * --------------------------------------------------------------------------------
         * If the database server cannot successfully prepare the statement, PDO::prepare() 
         * returns FALSE or emits PDOException (depending on error handling settings).
         * --------------------------------------------------------------------------------
         */
        $sql = 'INSERT INTO students (
                    classid,
                    userid,
                    firstname,
                    surname,
                    form,
                    gender
                ) VALUES (
                    :classid,
                    :userid,
                    :firstname,
                    :surname,
                    :form,
                    :gender
                )';
    
        $statement = $connection->prepare($sql);
    
        if (!$statement) {
            throw new UnexpectedValueException('The sql statement could not be prepared!');
        }
    
        /*
         * Bind the input parameters to the prepared statement.
         * 
         * -----------------------------------------------------------------------------------
         * Unlike PDOStatement::bindValue(), when using PDOStatement::bindParam() the variable 
         * is bound as a reference and will only be evaluated at the time that 
         * PDOStatement::execute() is called.
         * -----------------------------------------------------------------------------------
         */
    
        $bindings = array(
            ':classid' => $classid,
            ':userid' => $userid,
            ':firstname' => $firstname,
            ':surname' => $surname,
            ':form' => $form,
            ':gender' => $gender,
        );
    
        foreach ($bindings as $key => $value) {
            $bound = $statement->bindValue(
                    getInputParameterName($key)
                    , $value
                    , getInputParameterDataType($value)
            );
    
            if (!$bound) {
                throw new UnexpectedValueException('An input parameter could not be bound!');
            }
        }
    
        /*
         * Execute the prepared statement.
         * 
         * ------------------------------------------------------------------
         * PDOStatement::execute returns TRUE on success or FALSE on failure.
         * ------------------------------------------------------------------
         */
        $executed = $statement->execute();
    
        if (!$executed) {
            throw new UnexpectedValueException('The prepared statement could not be executed!');
        }
    
        /*
         * Get last insert id.
         */
        $lastInsertId = $connection->lastInsertId();
    
        if (!isset($lastInsertId)) {
            throw new UnexpectedValueException('The last insert id could not be read!');
        }
    
        /*
         * Close connection.
         */
        $connection = NULL;
    
        /*
         * Print results.
         */
        echo 'Provided data successfully added with the id: ' . $lastInsertId;
    } catch (PDOException $pdoException) {
        echo $pdoException->getMessage();
        exit();
    } catch (Exception $exception) {
        echo $exception->getMessage();
        exit();
    }
    
    /**
     * Get the name of an input parameter by its key in the bindings array.
     *  
     * @param int|string $key The key of the input parameter in the bindings array.
     * @return int|string The name of the input parameter.
     */
    function getInputParameterName($key) {
        return is_int($key) ? ($key + 1) : (':' . ltrim($key, ':'));
    }
    
    /**
     * Get the PDO::PARAM_* constant, e.g the data type of an input parameter, by its value.
     *  
     * @param mixed $value Value of the input parameter.
     * @return int The PDO::PARAM_* constant.
     */
    function getInputParameterDataType($value) {
        $dataType = PDO::PARAM_STR;
        if (is_int($value)) {
            $dataType = PDO::PARAM_INT;
        } elseif (is_bool($value)) {
            $dataType = PDO::PARAM_BOOL;
        }
        return $dataType;
    }
    

    感谢您的评论和回答。几个不同的用户建议允许空值@我将这些列的默认值设置为NULL。它起作用了

    几个月来(使用一个未准备好的MySQLi语句),我一直对它的工作方式感到困惑,但拒绝接受PDO语句中的这些插入


    无论如何,答案(都归功于@Sand、@Anshuman和@Lawrence)是将默认列值设置为NULL,这样就不管变量是否为空了。

    谢谢您的评论和回答。几个不同的用户建议允许空值@我将这些列的默认值设置为NULL。它起作用了

    几个月来(使用一个未准备好的MySQLi语句),我一直对它的工作方式感到困惑,但拒绝接受PDO语句中的这些插入


    不管怎样,答案(都归功于@Sand、@Anshuman和@Lawrence)是将默认列值设置为NULL,那么不管变量是否为空。

    不工作会带来什么?你有什么错误吗?您可以记录SQL异常吗?当用户提供所有值时,是否可以插入值?它不会插入行。没有错误,但我不确定我是否已将其设置为报告错误。@Billa如果我将$variables括在引号中(换句话说,将它们转换为值),它将允许您的数据库接受空值?不工作会导致什么后果?你有什么错误吗?您可以记录SQL异常吗?当用户提供所有值时,是否可以插入值?它不是插入t