MySQL: как проверить, является ли строка действительной датой, временем или датой - PullRequest
18 голосов
/ 22 апреля 2010

Когда я пытаюсь поместить значение в поле DATE, которое недопустимо, MySQL, кажется, вместо этого использует 0000-00-00.Есть ли способ, которым я могу сделать эту «проверку» без обновления поля DATE?И сделать это, например, из PHP?

Например, есть ли способ, которым я могу запросить сервер MySQL и спросить: «Эй, это DATE, TIME или DATETIME для вас?»

Или, может быть, есть еще лучший способ сделать это?

Ответы [ 12 ]

7 голосов
/ 17 июля 2014

Я использую этот синтаксис в своем приложении, и он работает как шарм!

SELECT DATE('2013-09-31') AS valid;

Моя система - Win7x64 с PHP 5.5 и MySQL 5.6.16

6 голосов
/ 22 апреля 2010

Вы можете проанализировать дату в соответствии с форматом, который вы хотите использовать, а затем вызвать checkdate, чтобы проверить, является ли она действительной датой. Обязательно прочитайте комментарии на http://php.net/manual/en/function.checkdate.php.

4 голосов
/ 02 марта 2016

Поскольку вопрос гласит MySQL , вот решение MySQL :

Очень сложно проверить, является ли поле датой из-за всех возможных форматов даты, которые необходимо учитывать. НО, если вы знаете, что форматы даты поля являются одним из следующих:

'yyyy-mm-dd'
'yyyy-mm-dd hh:mm:ss'
'yyyy-mm-dd whatever'

Этот код поможет вам:

 SELECT count(*) FROM `table` 
 WHERE DATE(STR_TO_DATE(`column`, '%Y-%m-%d')) IS NOT NULL
 AND `column` NOT REGEXP '^[0-9\.]+$'

В основном:

  • первое условие сообщает вам, является ли дата, но, к сожалению, не исключает числа (например: DATE(STR_TO_DATE(**1**, '%Y-%m-%d')) = '2001-00-00'
  • второй обеспечивает исключение чисел, в результате чего остаются только даты, соответствующие форматам, указанным выше.

Если count(*) равно >0, то это дата, если это 0, это что-то еще.

Примечание Этот метод работает со строками любого формата даты, если вы заранее знаете, в каком формате они следуют (я знаю, что это не всегда так, но все же полезно). Просто замените формат a priori в запросе

4 голосов
/ 24 апреля 2010

Вы можете просто использовать «постоянный» запрос, не используя временные таблицы и тестовые поля:

mysql> select day('2010-02-31 00:00:00');
+----------------------------+
| day('2010-02-31 00:00:00') |
+----------------------------+
|                       NULL | 
+----------------------------+
2 голосов
/ 07 октября 2017

SELECT WEEK(col) IS NOT NULL AS valid;

ИЛИ один из:

SELECT DAYNAME(col) IS NOT NULL AS valid;
SELECT TO_DAYS(col) IS NOT NULL AS valid;
SELECT TO_SECONDS(col) IS NOT NULL AS valid;
SELECT WEEKDAY(col) IS NOT NULL AS valid;
SELECT WEEKOFYEAR(col) IS NOT NULL AS valid;
SELECT YEARWEEK(col) IS NOT NULL AS valid;
2 голосов
/ 22 апреля 2010

Если вы выбираете режим сервера для сервера MySQL, который не допускает недопустимых значений даты, запрос, содержащий такое искаженное представление даты, вызовет ошибку вместо (молча) предположения 0000-00-00
см http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html

, например

$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly'); 
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$pdo->exec('CREATE TEMPORARY TABLE foo (id int auto_increment, d datetime, primary key(id))');

$query = "INSERT INTO foo (d) VALUES ('2010-02-31 12:15:18')";
foreach( array('ALLOW_INVALID_DATES', 'STRICT_ALL_TABLES') as $mode ) {
  echo $mode, ": "; flush();
  $pdo->exec("SET SESSION sql_mode='$mode'");
  $pdo->exec($query);
  echo "Ok.\n";
}

печать

ALLOW_INVALID_DATES: Ok.
STRICT_ALL_TABLES: 
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2010-02-31 12:15:18' for column 'd' at row 1' in [...]
1 голос
/ 15 января 2018

Я делаю это:

if(strtotime(trim($str)) {
    // persist trim($str) in db.        

}
0 голосов
/ 16 марта 2018

Чтобы проверить, является ли значение датой, вы можете использовать day(dateToCheck) = 0

0 голосов
/ 30 марта 2017

DATETIME - в SQL

SELECT your_unreliable_datetime_column, CAST(your_unreliable_datetime_column as DATETIME)
FROM some_cool_table
WHERE
CAST(your_unreliable_datetime_column as DATETIME) IS NOT NULL
AND
your_unreliable_datetime_column = CAST(your_unreliable_datetime_column as DATETIME)

Это должно выбрать только действительные DATETIME s, также должно применяться к DATE и TIME соответственно , но не проверено ...

Я не нашел никакой документации по CAST() возвращаемому значению при ошибке преобразования, но документация охватывает особый случай - возможный сбой - который возвращаетNULL:

Для преобразования «нулевой» строки даты в дату CONVERT() и CAST() возвращают NULL и выдают предупреждение при включении режима NO_ZERO_DATE SQL

Кроме того, из моих тестов кажется , что CAST() ведет себя так же при любой сбой преобразования - возвращает NULL и выдает предупреждение.

Я проверял это на MariaDB 10.0.30

0 голосов
/ 17 марта 2015

Может быть, вам нужно создать базу данных с BLACKHOLE движком, читайте здесь .И проверьте исключение, сгенерированное PDOException.

$dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'p@s5W0Rd!!!', array(PDO::ATTR_PERSISTENT => true));

// CREATE DATABASE test;
// CREATE TABLE test.foo ( bar DATETIME ) ENGINE=BLACKHOLE;

try {
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $dbh->beginTransaction();

    $dateTime = new DateTime();
    $dateTime = $dateTime->format('c');
    $dbh->exec("INSERT INTO foo (bar) VALUES ('".$dateTime."')");
    $dbh->commit();
} catch (PDOException $e) {
    $errorInfo = $dbh->errorInfo();

    if ($e->getCode() === '22007'
        and $dbh->errorCode() === '22007'
        and $errorInfo[0] === '22007'
        and preg_match('/^incorrect datetime/', strtolower($errorInfo[2])) === 1) {

        throw new Exception($errorInfo[2], (int) $e->getCode());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...