【问题标题】:SQLite INSERT & SELECT is not workingSQLite 插入和选择不起作用
【发布时间】:2018-02-19 17:15:38
【问题描述】:

简单的事情:我的代码只是不工作。 INSERT 和 SELECT 在我的 PDO 中都不起作用。可能我有问题,但我不是代码大师,所以我需要你的帮助。

if (isset($_POST['submit']))
{
try 
    {
        $connection = new PDO('sqlite:../tracker.db');

        $name       = $_POST['name'];
        $unitsize   = $_POST['unitsize'];
        $line       = $_POST['line'];
        $mmr        = $_POST['mmr'];
        $lifespan   = $_POST['lifespan'];
        $connection->exec("INSERT INTO unit (name, unitsize, line, mmr, lifespan) 
        VALUES ('$name', '$unitsize', '$line', '$mmr', '$lifespan')");

        $new_unit = "SELECT unit_id
                     FROM unit
                     ORDER BY unit_id DESC
                     LIMIT 1";
        foreach ($connection->query($new_unit) as $row) {
        $id = $row['unit_id'];
        };

    }
    catch(PDOException $error) 
    {
        echo $error->getMessage();
    }
}

当然我知道没有记录的 SELECT 是行不通的……但我的初学者的直觉告诉我,它也可能有错误。

PS:我知道,代码可能有点乱......对不起你的眼睛流血:(

编辑: 我想要实现的目标

  1. 有一个数据库 tracker.db 与现有表(由 SQLite 浏览器确认)
  2. 我想从我的form 中插入一些数据。
  3. 插入后,我想将数据库中注册的最后一个 unit_id 放入变量 $id(unit_id 是 AUTOINCREMENT 和 PRIMARY KEY)
  4. 就是这样

【问题讨论】:

  • 1.您应该根据提交条件要求文件。
  • 3.您的网络服务器的错误日志说明了什么?
  • 你的代码没有意义。您设置了 SELECT,但从不执行它 - 显然它不起作用。然后执行 INSERT,它实际上可能确实有效。然后,您尝试在该 INSERT 之后读取值,但再也不会运行 SELECT 来检索要读取的数据,这 再次 无法工作。你需要学会阅读你正在编写的代码,而不是仅仅敲打键盘写一些随机的东西并希望它们能正常工作。
  • @JayBlanchard 什么都没有,没有记录

标签: php sqlite pdo


【解决方案1】:

好吧,通过查看您的代码,我可以说错误(至少一个)在于以下部分:

  • 连接创建。
  • SQL 语句 - 撇号 (')。
  • 未捕获,故障信号,返回值PDO::exec() 或/和PDO::query()。关于它们的定义,您正在以正确的方式使用这两个函数,但它们可能在失败时返回 FALSE。您根本没有处理的情况,并且在 php.net 上相应文档的“返回值”部分中进行了说明。

所以,因为您的代码的问题是您不知道它为什么不起作用,例如您没有收到任何错误或迹象,我想向您展示使用错误报告 + 准备好的语句 + 验证 + 异常处理的完整方法。请注意,如果您想编写安全可靠的 PDO 解决方案,所有这四个元素都是必需的。更重要的是,当您以适当的方式应用它们时,您将始终知道问题(或更多)在哪里。而且您在代码编写方面的效率会大大提高,因为您不会再浪费时间(有时是几个小时!)来查找错误。

此外,如何构建代码取决于您自己。我在这里向您展示了一个程序表格,您可以在其中轻松地执行这些步骤。更好的形式是以面向对象的方式实现。

建议:

  • 始终准备 sql 语句(阅读this)以避免恶意的数据库注入。在您的情况下,这意味着您必须使用PDO::prepare() + PDOStatement::execute() 而不是PDO::exec(阅读PDO::exec on php.net 中的“说明”)。
  • PDO 是一个非常强大的数据访问抽象系统。但是,为了正确使用它,您需要始终阅读您正在使用的每个功能的文档,特别是“返回值”部分。这将是“必须”的,因为在某些情况下,在失败时,可以以 bool FALSE OR 的形式返回值,并且可以抛出异常。然后必须妥善处理这些案件。例如PDO::prepare():

如果数据库服务器无法成功准备语句, PDO::prepare() 返回 FALSE 或发出 PDOException(取决于错误 处理)。

如果您有任何不清楚的地方,请随时提出。

祝你好运。

<?php

/*
 * Try to include files using statements 
 * only on the top of the page.
 */
require "../config.php";
require "../common.php";

/*
 * Set error reporting level and display errors on screen.
 * 
 * =============================================================
 * Put these two lines in a file to be included when you need to
 * activate error reporting, e.g the display of potential errors 
 * on screen.
 * =============================================================
 * Use it ONLY ON A DEVELOPMENT SYSTEM, NEVER ON PRODUCTION !!!
 * If you activate it on a live system, then the users will see
 * all the errors of your system. And you don't want this !!!
 * =============================================================
 */
error_reporting(E_ALL);
ini_set('display_errors', 1);

/*
 * ===================================================
 * Two functions used for automatically binding of the
 * input parameters. They are of course not mandatory, 
 * e.g. you can also bind your input parameters one 
 * by one without using these functions. But then
 * you'd have to validate the binding of each input
 * parameter one by one as well.
 *  
 * Put these two functions in a file to be included,
 * if you wish.
 * ===================================================
 */

/**
 * 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) {
    if (is_int($value)) {
        $dataType = PDO::PARAM_INT;
    } elseif (is_bool($value)) {
        $dataType = PDO::PARAM_BOOL;
    } else {
        $dataType = PDO::PARAM_STR;
    }

    return $dataType;
}

/*
 * ======================
 * Hier begins your code.
 * ======================
 */
try {
    // Read from HTTP POST.
    $name = $_POST['name'];
    $unitsize = $_POST['unitsize'];
    $line = $_POST['line'];
    $mmr = $_POST['mmr'];
    $lifespan = $_POST['lifespan'];

    // Create a PDO instance as db connection to sqlite.
    $connection = new PDO('sqlite:../tracker.db');

    // The sql statement - it will be prepared.
    $sql = 'INSERT INTO unit (
                name,
                unitsize,
                line,
                mmr,
                lifespan
            ) VALUES (
                :name,
                :unitsize,
                :line,
                :mmr,
                :lifespan
            )';

    // The input parameters list for the prepared sql statement.
    $bindings = array(
        ':name' => $name,
        ':unitsize' => $unitsize,
        ':line' => $line,
        ':mmr' => $mmr,
        ':lifespan' => $lifespan,
    );

    // Prepare the sql statement.
    $statement = $connection->prepare($sql);

    // Validate the preparing of the sql statement.
    if (!$statement) {
        throw new UnexpectedValueException('The sql statement could not be prepared!');
    }

    /*
     * Bind the input parameters to the prepared statement 
     * and validate the binding of the input parameters.
     * 
     * =================================================================
     * This part calls the two small functions from the top of the page:
     *  - getInputParameterName()
     *  - getInputParameterDataType()
     * =================================================================
     */
    foreach ($bindings as $key => $value) {
        // Read the name of the input parameter.
        $inputParameterName = getInputParameterName($key);

        // Read the data type of the input parameter.
        $inputParameterDataType = getInputParameterDataType($value);

        // Bind the input parameter to the prepared statement.
        $bound = $statement->bindValue($inputParameterName, $value, $inputParameterDataType);

        // Validate the binding.
        if (!$bound) {
            throw new UnexpectedValueException('An input parameter could not be bound!');
        }
    }

    // Execute the prepared statement.
    $executed = $statement->execute();

    // Validate the prepared statement execution.
    if (!$executed) {
        throw new UnexpectedValueException('The prepared statement could not be executed!');
    }

    /*
     * Get the id of the last inserted row.
     * You don't need to call a SELECT statement for it.
     */
    $lastInsertId = $connection->lastInsertId();

    /*
     * Display results. Use it like this, instead of a simple "echo".
     * In this form you can also print result arrays in an elegant
     * manner (like a fetched records list).
     * 
     * Theoretically, this statement, e.g. the presentation of results 
     * on screen, should happen outside this try-catch block (maybe in
     * a HTML part). That way you achieve a relative "separation of 
     * concerns": separation of the fetching of results from the 
     * presentation of them on screen.
     */
    echo '<pre>' . print_r($lastInsertId, TRUE) . '</pre>';

    // Close the db connecion.
    $connection = NULL;
} catch (PDOException $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    // echo $exc->getMessage();
    // $logger->log($exc);
    exit();
} catch (Exception $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    // echo $exc->getMessage();
    // $logger->log($exc);
    exit();
}
?>

【讨论】:

  • 首先,谢谢。第二:由于通知警报,我不得不将部分代码放在if(isset($_POST['submit']))。您的代码正在运行......但我得到一个不执行 The prepared statement could not be executed! 的异常。我不需要具有良好安全性的精美解决方案(好吧,我根本不需要安全性。当然,我很感激你想教我好习惯),我只需要它工作。
  • 不客气。是的,我忘了把那个isset 部分。我重新编辑了我的答案:我刚刚在catch 块中添加了打印整个异常对象的能力(仅在开发时这样做!)。现在你会看到问题出在哪里。是的,您需要一个可行的解决方案。但是,您知道,所有这些步骤实际上都是工作解决方案所必需的。例如。它们不是花哨的东西。很高兴成为:-)
  • 问题正是我在引用中提出的问题(在我的回答中),例如该语句在失败时返回 FALSE。现在,让我们找出确切的问题:
  • 首先:在$bindings 中写入值,而不是变量。喜欢:':name' =&gt; 'jane', ':unitsize' =&gt; 1,... 再试一次。
  • 然后在 db 编辑器中直接使用相同的值运行 sql insert 语句:INSERT INTO unit (...) VALUES ('jane', 1, ...);
猜你喜欢
  • 2011-12-16
  • 1970-01-01
  • 2023-03-13
  • 2012-07-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多