php - PDO 使用 MySQL 的 NOW()

标签 php mysql sql pdo

我将如何在 PDO 准备好的语句中使用 MySQL 的 NOW(),或者如何使用它来解决问题,同时记住 Apache 服务器和数据库服务器可能有轻微的当前时间不匹配(几秒钟),或者在极少数情况下可能是时区分开?

我的代码中有以下函数:

try {
    $dbh->insert("users", array(
        "email" => $email,
        "password" => $password,
        "salt" => $salt,
        "ingame" => $ingame,
        "kiosk" => $kiosk
    ));
} catch (PDOException $ex) {
    error($ex);
}

哪个调用:

/**
 * Inserts data into a table. Data must be given in key-value pairs.
 * 
 * Example: $dbh->insert("table", array(
 *                                  "data1" => $data1,
 *                                  "data2" => $data2
 *                                  );
 * 
 * @param type $table   The table to insert to
 * @param type $keyvaluepairs   The key-value pairs.
 * @return type The statement that this query produced.
 */
public function insert($table, $keyvaluepairs) {
    $sql = "INSERT INTO `{$table}` (";
    $values_sql = ") VALUES(";
    $values = array();
    foreach ($keyvaluepairs as $key => $value) {
        $sql .= "`${key}`, ";
        $values_sql .= "?, ";
        $values[] = $value;
    }
    $query = substr($sql, 0, -2).substr($values_sql, 0, -2).")";
    return $this->query($query, $values);
}

哪个调用:

//TODO update documentation to show it also handles associative arrays with bindvalue
/**
 * Can be called to create a query. Use either unnamed or named placeholders for the prepared statements.
 * 
 * Example: $dbh->query("INSERT INTO table (data1, data2) VALUES(?, ?)", array($data1, $data2));
 * 
 * @param type $query   The input query, including unnamed or named placeholders
 * @param type $values  The input values. If it's not an array, then it will be an one-element array
 * @return type The statement constructed by this query
 */
public function query($query, $values = array()) {
    if (!is_array($values)) {
        $values = array($values);
    }
    $statement = $this->dbh->prepare($query);
    $statement->setFetchMode(PDO::FETCH_OBJ);
    $i = 1;
    if (is_assoc($values)) {
        foreach ($values as $key => $value) {
            $statement->bindValue($key, $value);
        }
    }
    else {
        foreach ($values as $value) {
            $statement->bindValue($i++, $value);
        }
    }
    $statement->execute();
    return $statement;
}

我有这个功能:

function is_assoc($array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

所以这里的问题是我不能使用自定义 MySQL 查询来插入,因为为了简单起见我已经封装了这些查询,但我仍然希望能够插入 NOW () 使用 TIMESTAMP/CURRENT_TIMESTAMP()

我希望您理解这个问题需要一个解释性的答案,因为我已经阅读了“正常”答案并表明它们不能满足我的需求。

更新:我已将 const SQL_NOW = 1; 添加到我的 DBH 类中,但是现在我想修改 insert 像这样:

public function insert($table, $keyvaluepairs) {
    $sql = "INSERT INTO `{$table}` (";
    $values_sql = ") VALUES(";
    $values = array();
    foreach ($keyvaluepairs as $key => $value) {
        if ($value == SELF::SQL_NOW) {
            $sql .= "NOW(), ";
        }
        else {
            $sql .= "`${key}`, ";
            $values_sql .= "?, ";
            $values[] = $value;
        }
    }
    $query = substr($sql, 0, -2).substr($values_sql, 0, -2).")";
    return $this->query($query, $values);
}

这可能是一个合适的解决方案,但是我不能使用1作为SQL_NOW值,因为如果我想要的话它会失败插入一个整数1。如果我采用此解决方案,SQL_NOW 会有什么值(value)?甚至可以赋予它没有值(value)吗?

最佳答案

问得好!

这是一个完美的例子,清楚地表明了为什么所有这些众多的 insert()、update() 以及所有其他旨在替代 SQL 的东西在设计上都是错误的 .

NOW() 并不是您将面临的唯一问题。只是因为SQL 并不是一种乍一看那么愚蠢的语言。它是故意发明的。它的可靠性已经经过数十年的验证。这意味着在学习 PHP 的同时编写完整的 SQL 作为练习并不是那么容易。

因此,您能做的最好的事情就是保持 SQL 不变。

您真正需要的是一两个辅助函数。自动化重复性任务。就这些。而 SQL 必须保持原样。这将使您能够使用它的所有功能,包括使用函数、带参数的函数(!)、查询修饰符(例如“INSERT IGNORE”)或扩展语法(例如 JOINS)。

如果您使用 PDO,则不是那么简单但可行。

但是,唯一正确的解决方案是为 SET 语句使用特殊类型的占位符

$data = array(
        "email"    => $email,
        "password" => $password,
        "salt"     => $salt,
        "ingame"   => $ingame,
        "kiosk"    => $kiosk,
);
$dbh->query("INSERT INTO ?n SET reg = NOW(), ?u","users", $data);

只需一行即可解决所有困惑和许多许多其他问题。
只需一个 query() 方法即可运行您想要的任何查询,甚至是 REPLACE INTO

更新。

看看你在做什么!

您计划类(class)是为了简化事情。但目前你正在让它变得越来越复杂。最终,您将得到一个庞大的巨人,其语法不一致,甚至连它的创建者和其他人也几乎无法理解无数的异常。而且仍然不允许您运行一些查询。

请在为时已晚之前重新考虑您的设计。

关于php - PDO 使用 MySQL 的 NOW(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20703218/

相关文章:

java - Hibernate:如何根据条件选择返回 0 和 null 的最大列值

mysql - 如何从 UNION ALL 之外的另一个表获取列值?

php - 使用 Simple Html Dom 通过 ajax 动态加载 Scrape Div 的内容

php 变量在 jquery 或 javascript highchart 中正确传递

javascript - AJAX + jQUERY : load div instantly, 然后每隔 X 秒刷新一次

mysql - 如何将 mySql SQL 脚本转换为 MS SQL 脚本?

php - 按每年唯一的月份分组,而不仅仅是月份

mysql - 带有更新的 Mysql 存储过程

PHP MySQL 不将数据插入数据库并将产品 ID 返回为 0

java - JDBC - 创建/准备好的语句 : What happens and are they concurrent?