SQLite在文本字段中未正确排序日期

时间:2019-01-23 13:36:40

标签: php sqlite date

我有一个php脚本,可以将一些日程表保存在sqlite数据库中。一直有效,直到近两周前我注意到sqlite的行为很奇怪。我将日期保存在文本字段中,无法按日期对记录进行排序。

例如,我有一些最近添加的2月日期,如果我运行查询以返回8月22日之后的日期:

SELECT `date`, hex(`date`), substr(`date`, 1, 1), substr(`date`, 1) 
FROM Schedules WHERE `date` > '2019-08-22' order by `date`

我得到记录:

`date`              hex(`date`)                substr(`date`, 1, 1) substr(`date`, 1)
2019-08-22 13:00    323031392D30382D32322031333A3030    2           2019-08-22 13:00
2019-02-04 12:00    323031392D30322D30342031323A3030    2           2019-02-04 12:00
2019-02-18 12:00    323031392D30322D31382031323A3030    2           2019-02-18 12:00
2019-03-04 12:00    323031392D30332D30342031323A3030    2           2019-03-04 12:00

第一条记录是正确的,我将其包括在内是为了与错误的记录进行比较。我考虑过在实际数字之前添加一些字符,但从十六进制列来看似乎并非如此。我什至试图请求大于'3000'的日期来排除破折号(也许他们有一些Unicode字符),并且它会继续返回以前结果的最后三条记录。

该表定义为:

CREATE TABLE `Schedules` (
  `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  `date` TEXT
);

我要添加记录的php代码是:

class Schedule {
    public static function add_schedule($programmed_date, $programmed_time, $options) {
        $result = 0;
        date_default_timezone_set('Europe/Rome');
        $date = DateTime::createFromFormat('d/m/Y H:i', "$programmed_date $programmed_time");
        $now = new DateTime();
        if ($date < $now)
            return -1;
        $dbh = self::connect_to_database();
        $stmt = $dbh->prepare('INSERT INTO Schedules(`date`) VALUES (:date)');
        $stmt->bindValue(':date', $date->format('Y-m-d H:i'), SQLITE3_TEXT);
        try {
            $execution = $stmt->execute();
            if ($execution !== FALSE)
                $result = 1;
        }
        catch (Exception $ex) {}
        finally {
            $stmt->closeCursor();
        }
        $dbh = null;
        return $result;
    }

    private static function connect_to_database() {
        $db_path = Credentials::read_info('schedule')['db_path'];
        try {
            $dbh = new PDO('sqlite:'.$db_path);
            $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
            $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        catch(PDOException $e) {
            echo 'Connection failed: '.$e->getMessage();
            exit;
        }
        return $dbh;
    }
}

目前,我无法猜测代码出了什么问题。 sql语句应仅返回第一条记录,而不是四条。有什么想法吗?谢谢。

SQLite DateTime comparison导致我进入https://www.sqlite.org/lang_datefunc.html,如果运行查询,我找到了一种解决方法:

SELECT `date`, hex(`date`), substr(`date`, 1, 1), substr(`date`, 1) 
FROM Schedules WHERE datetime(`date`) > datetime('2019-08-22') order by `date`

它可以正常工作,只返回8月22日的记录。但是,我一直想知道为什么在https://www.db-fiddle.com/f/ar9JxpaCo2wcQB1MobyaVv/0发生转储时,纯文本比较和顺序使结果搞乱了,您清楚地看到我在这里编写的第一个查询返回了不同的(正确的)结果。 如果您想直接尝试访问我的数据库,可以从here

下载

2 个答案:

答案 0 :(得分:2)

嗯,那很有趣。我下载了数据库,并在数据库浏览器中播放了sqlite(只读),直到发现一些有趣的东西。它以胖手指date > '21'开始(它在3个较早的日期中找到了它们)。最终,此sql select *,typeof(date) from Schedules揭示了一些内容

349|2019-08-22 13:00|text
374|2019-02-04 12:00|blob
375|2019-02-18 12:00|blob
376|2019-03-04 12:00|blob

我创建了一个复制子,如果从SQLITE3_TEXT中删除了bindValue,它将把日期插入为文本。

答案 1 :(得分:1)

在@DinoCoderSaurus中回答,您有理由说明您的数据表现不正常。
我发现的解决方法是:

margin: auto

这样,您将获得预期的结果。
空字符串串联会将.special-background .row > div { height: 100%; } .img-fluid { max-heihgt: 100%; width: auto; margin: auto; } 转换回WHERE date || '' > '2019-08-22'