web-dev-qa-db-ja.com

str_to_dateの値が正しくありません

次の形式を使用して、VARCHAR列から読み取り、TIME列にデータを挿入する簡単なプロシージャを実行しています。

_STR_TO_DATE(vTestTime, '%H:%i'). 
_

エラーが出ます

SQLエラー(1411):関数str_to_dateの不正な日時値:'09:22 '

HeidiSQLクライアントから実行すると、同様のステートメントSELECT STR_TO_DATE("09:22", "%H:%i")がNULLを返すことがわかりました。

この構文が機能していて、設定を変更したことに気づいていないと思いますが、私が間違ったことを提案できますか?

編集:最近の変更を行ったことを思い出して、同じサーバーにWordpressデータベースをインストールしました。何らかの影響があったのでしょうか?

サーバー上で実行されるものは次のとおりです。

_mysql> select str_to_date("09:22", "%H:%i");

+-------------------------------+

| str_to_date("09:22", "%H:%i") |

+-------------------------------+

| NULL                          |

+-------------------------------+

1 row in set, 1 warning (0.00 sec)

Warning (Code 1411): Incorrect datetime value: '09:22' for function str_to_date
_
1
user147997

これはバグのように見えます(技術的にはバグではありませんが、回答の終わりにある最初の編集を参照してください)。

MySQL 5.7.20および5.7.21(Centos 7.4が重要な場合)での動作を確認します。

mysql> select str_to_date("09:22", "%H:%i");
+-------------------------------+
| str_to_date("09:22", "%H:%i") |
+-------------------------------+
| NULL                          |
+-------------------------------+
1 row in set, 1 warning (0.00 sec)

警告はコード1411 Incorrect datetime value: '09:22' for function str_to_dateです。

ANSI_QUOTESが有効になっておらず、単一引用符を使用すると同じ警告が表示されます。

私が ドキュメント を読んで理解していることから、クエリは機能するはずです:

STR_TO_DATE()は、フォーマット文字列に日付と時刻の両方の部分が含まれている場合はDATETIME値を返し、文字列に日付と時刻の部分のみが含まれている場合はDATEまたはTIME値を返します。

このクエリは、日付と時間の部分を含み、機能します。

mysql> SELECT STR_TO_DATE("2017-03-17 09:22","%Y-%m-%d %H:%i");
+--------------------------------------------------+
| STR_TO_DATE("2017-03-17 09:22","%Y-%m-%d %H:%i") |
+--------------------------------------------------+
| 2017-03-17 09:22:00                              |
+--------------------------------------------------+
1 row in set (0.00 sec)

MariaDB 10.2.14で元のクエリを実行すると、正しく機能します。

MariaDB [(none)]> select str_to_date("09:22", "%H:%i");
+-------------------------------+
| str_to_date("09:22", "%H:%i") |
+-------------------------------+
| 09:22:00                      |
+-------------------------------+
1 row in set (0.00 sec)

EDIT:これは以前にバグとして報告されました、ここを参照してください: https://bugs.mysql.com/bug.php?id = 80064

NO_ZERO_DATEまたはNO_ZERO_IN_DATE SQLモードが有効な場合、ゼロの日付または日付の一部は許可されません。その場合、STR_TO_DATE()はNULLを返し、警告を生成します。

これらのモードは、MySQL 5.7ではデフォルトで有効になっています(MariaDB 10.2では無効です)。したがって、これらをsql_modeシステム変数から削除すると、目的の結果が得られます。

mysql> SET sql_mode='';
mysql> select STR_TO_DATE("09:22", "%H:%i");
+-------------------------------+
| STR_TO_DATE("09:22", "%H:%i") |
+-------------------------------+
| 09:22:00                      |
+-------------------------------+
1 row in set (0.00 sec)

EDIT 2:sql_modeシステム変数から誤って役立つ/重要なモードを削除したくないので、理想的には特定のモード、この場合はNO_ZERO_DATEおよびNO_ZERO_IN_DATE。これは次の方法で行うことができます:

SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'NO_ZERO_DATE', '');
SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'NO_ZERO_IN_DATE', '');

(セッションだけでなく、グローバルスコープを変更する場合は、SET GLOBAL sql_mode...を使用します。)

MySQL構成ファイルでsql_modeを設定したい場合は、それを「ハードコード」する必要があると思います。つまり、使用しているバージョンのデフォルトモードを確認し、削除します。望ましくないモード、および結果の文字列を追加します。 .cnfファイルの[mysqld]セクションに:

sql-mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION  

これはMySQL 5.7では正しいはずです。次のバージョンにアップグレードするときは、設定をもう一度更新する必要があります。

ストアドプロシージャは独自のsql_modesで実行されることに注意してください。

MySQLは、ルーチンが作成または変更されたときに有効なsql_modeシステム変数設定を保存し、ルーチンの実行開始時の現在のサーバーSQLモードに関係なく、常にこの設定を有効にしてルーチンを実行します。

ソース: MySQLストアドプロシージャのドキュメント

ストアドプロシージャ内でsql_modeを変更することもできます。

2
dbdemon