MySQLでDATEまたはDATETIMEのデフォルト値を設定するときのエラー


124

MySql Server 5.7.11を実行していて、この文は次のとおりです。

updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

機能していません。エラーを与える:

ERROR 1067 (42000): Invalid default value for 'updated'

しかし、次のとおりです。

updated datetime NOT NULL DEFAULT '1000-01-01 00:00:00'

ちょうど動作します。

DATEの場合も同じです。

傍注として、それはMySQLドキュメントで言及されています

DATEタイプは、日付部分があるが時間部分がない値に使用されます。MySQLはDATE値を取得して「YYYY-MM-DD」形式で表示します。サポートされる範囲は「1000-01-01」から「9999-12-31」です。

彼らがまた言っても:

無効なDATE、DATETIME、またはTIMESTAMPの値は、適切なタイプ(「0000-00-00」または「0000-00-00 00:00:00」)の「ゼロ」値に変換されます。

MySQLドキュメントの2番目の引用も考慮に入れて、なぜそれがそのエラーを引き起こしているのかを誰かに教えてもらえますか?


11
明らかに無意味なデフォルトが必要なのはなぜですか?日付が不明な場合は、まさにそれNULLが目的です。
トムH

注意点としては:SQLフィドルのバージョン5.6で、この作品- sqlfiddle.com/#!9/02c98
ゴードンリノフ16

@Karlosが更新された回答を確認します。
geeksal

回答:


209

エラーは、最新のMYSQL 5.7ドキュメントに従って厳密モードである可能性があるSQLモードが原因です

MySQLドキュメント5.7は言う

厳密モードは、サーバーが有効な日付として「0000-00-00」を許可するかどうかに影響します。厳密モードが有効でない場合、「0000-00-00」が許可され、挿入によって警告は生成されません。厳密モードが有効になっている場合、IGNOREが指定されていない限り、 '0000-00-00'は許可されず、挿入はエラーを生成します。INSERT IGNOREおよびUPDATE IGNOREの場合、 '0000-00-00'が許可され、挿入により警告が生成されます。

MYSQLモードを確認するには

SELECT @@GLOBAL.sql_mode global, @@SESSION.sql_mode session

STRICT_TRANS_TABLESモードを無効にする

ただし、フォーマットを許可するには 0000-00-00 00:00:00、mysql構成ファイルまたはコマンドでSTRICT_TRANS_TABLESモードを無効にする必要があります

コマンドで

SET sql_mode = '';

または

SET GLOBAL sql_mode = '';

キーワードを使用する GLOBALは、スーパー特権が必要であり、それ以降、すべてのクライアントが接続する操作に影響します

上記が機能しない場合は、/etc/mysql/my.cnf(ubuntuに従って)に移動してコメントアウトするよりもSTRICT_TRANS_TABLES

また、サーバーの起動時にSQLモードを永続的に設定する場合はSET sql_mode=''my.cnfLinuxまたはMacOSに組み込みます。Windowsの場合、これはmy.iniファイルで行う必要があります。

注意

ただし、MYSQL 5.6ではデフォルトでストリクトモードは有効になっていません。したがって、MYSQL 6のドキュメントにあるように、エラーは発生しません

MySQLでは、「ゼロ」値「0000-00-00」を「ダミー日付」として保存できます。これは、NULL値を使用するよりも便利な場合があり、使用するデータとインデックスのスペースが少なくなります。'0000-00-00'を禁止するには、NO_ZERO_DATE SQLモードを有効にします。

更新

@ Dylan-Suが言っているバグの問題について:

これは、MYSQLが時間の経過とともに進化していく方法であり、製品のさらなる改善に基づいていくつかの変更が行われるバグではないと思います。

ただし、NOW()関数に関する別の関連するバグレポートがあります。

日時フィールドはデフォルトのNOW()を受け入れません

もう1つの便利なメモ [ TIMESTAMPとDATETIMEの自動初期化と更新を参照]

MySQL 5.6.5以降、TIMESTAMPおよびDATETIMEカラムは自動的に初期化され、現在の日時(つまり、現在のタイムスタンプ)に更新されます。5.6.5より前では、これはTIMESTAMPにのみ当てはまり、テーブルごとに最大で1つのTIMESTAMP列に当てはまります。以下の注記では、最初にMySQL 5.6.5以降の自動初期化と更新について説明し、次に5.6.5より前のバージョンの違いについて説明します。

NO_ZERO_DATEに関する更新

MySQLの5.7.4以降、このモードは非推奨になりました。以前のバージョンでは、設定ファイルの該当する行をコメント化する必要があります。NO_ZERO_DATEのMySQL 5.7ドキュメントを参照してください


5
UPDATE IGNOREは私が探していたものです👍🏻–
Afanasii Kurakin

2
違う。STRICT_TRANS_TABLESローカルとサーバーの両方のMySQLインスタンスを持っています。ただし、0000-00-00ローカルインスタンスには簡単に挿入できますが、サーバーインスタンスには挿入できません。エラーがスローされます。どうして?サーバーのMySQL設定がNO_ZERO_DATE有効になっているためです。そして私の地元にはそれがありません。
グリーン

わかりました@Green該当する場合は、答えを
見つけて

4
私の場合、「SET sql_mode = ""」は機能しませんでした。'SET GLOBAL sql_mode = "";' 私のために仕事をしました。
arjen Stens 2017

またNO_ZERO_DATE削除する必要があります
Preshan Pradeepa 2017年

18

MySql 5.7.14のWAMP 3.0.6でこのエラーが発生しました。

ソリューション

c:\wamp\bin\mysql\mysql5.7.14\my.iniからの ファイルの70行目を変更します(あなたのiniファイルが変更されていない場合)

sql-mode= "STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_AUTO_CREATE_USER"

sql-mode="ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_AUTO_CREATE_USER"

すべてのサービスを再起動します。

これにより、厳密モードが無効になります。ドキュメントによれば、「ストリクトモード」とは、どちらか一方または両方のモードSTRICT_TRANS_TABLESまたはSTRICT_ALL_TABLES有効なモードを意味します。ドキュメントは言います:

「MySQL 5.7のデフォルトSQLモードには、ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER、およびNO_ENGINE_SUBSTITUTIONのモードが含まれています。」


14

データがNULLと日付フィールドの0000-00-00の間で混在する状況になりました。しかし、「0000-00-00」をNULLに更新する方法がわかりませんでした。

 update my_table set my_date_field=NULL where my_date_field='0000-00-00'

もう許可されていません。私の回避策は非常に簡単でした:

update my_table set my_date_field=NULL where my_date_field<'1000-01-01'

すべての不正なmy_date_field値(正しい日付かどうかに関係なく)はこの日付の前からのものだったためです。


2
完璧な迅速なソリューション。<'0000-01-01'もちろん有効な日付なので、実際に使用することもできます。
リッキーマクマスター2018

5

構成構文の問題

* nixシステムでの一部のバージョンのMYSQL(テスト済み5.7。*)では、次の構文を使用する必要があります。

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

これらは動作しません:

引用符をダッシュ​​しない

sql-mode=NO_ENGINE_SUBSTITUTION

下線なしの引用符

sql_mode=NO_ENGINE_SUBSTITUTION

下線と引用符

sql_mode="NO_ENGINE_SUBSTITUTION"

設定値とsql-modeのより完全なレビュー:

永続的なSQLモードフラグを設定する方法


5

最初に現在のセッションを選択sql_mode

SELECT @@SESSION.sql_mode;

次に、そのデフォルト値のようなものが得られます

'ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER、NO_ENGINE_SUBSTITUTION'

そしてsql_modeなしで設定'NO_ZERO_DATE'

SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

助成金がある場合は、次のこともできますGLOBAL

SELECT @@GLOBAL.sql_mode;
SET GLOBAL sql_mode = '...';

4

次の行を追加してください: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

ファイル内: /etc/mysql/mysql.conf.d/mysqld.cnf

その後 sudo service mysql restart


1
5.7.23で動作します。
user2513149 '25

1
私はおそらくSELECT @@SESSION.sql_mode;最初に提案するでしょう 、そして彼らはそれがあなたに与えるものからNO_ZERO_IN_DATE、NO_ZERO_DATE、そしてSTRICT_TRANS_TABLESを削除します。これにより、有効にした他の設定を保持できます。SQLモードに設定されているのは、これら2つの項目だけではありません。それらすべてが何をしているのかわからないが、私は現時点でそれらを削除する危険を冒したくない。
Radley Sustaire

2

5.7.8で動作します。

mysql> create table t1(updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00');
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t1;
+-------+-------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                            |
+-------+-------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+-------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.8-rc  |
+-----------+
1 row in set (0.00 sec)

SQLFiddleを作成して、問題を再現できます。

http://sqlfiddle.com/

MySQL 5.6および5.7.8で機能するが、5.7.11では失敗する場合。次に、それはおそらく5.7.11のリグレッションバグです。


1

MySQL Workbenchの問題を解決するには(サーバー側でソリューションを適用した後):

環境設定パネルでSQL_MODEをTRADITIONALに削除します。

ここに画像の説明を入力してください


1

この答えは、MySQL 5.7のみに対するものです。

Bestは実際にはsql_modeを空白で設定するのではなく、代わりにPHPでセッション変数を使用します。

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

したがって、少なくとも別のデフォルト値を維持します。

mysqlのドキュメントが明確でないのはおかしいです。sql_modeでこのデフォルト値を削除する必要があります。

NO_ZERO_IN_DATE、NO_ZERO_DATE、わかりましたが、将来のバージョンでは廃止される予定です。

STRICT_ALL_TABLES、これを使用すると、パラメータは無視されるため、削除する必要もあります。

最後にTRADITIONALもですが、ドキュメントではこのパラメーターについて説明しています。「列に誤った値を挿入すると、「警告ではなくエラーを与える」」、このパラメーターでは、ゼロの値を持つ日付は挿入されませんが、はいなしです。

MySQLは実際にはこれらのパラメーターと組み合わせで構成されていません。


0

オプションの組み合わせ mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64)

投げません:

STRICT_TRANS_TABLES + NO_ZERO_DATE

スロー:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

/etc/mysql/my.cnfUbuntuでの私の設定:

[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"


0

ディレクトリxamp / mysql / binで「my.ini」を開き、次の行を変更します。Sql_nodefor->

「sql_mode = NO_ENGINE_SUBSTITUTION、NO_ZERO_DATE」

「NO_ZERO_IN_DATE」を削除


Stackoverflowへようこそ。回答を読みやすくするために、適切なコード形式を使用してください。
vlizana
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.