web-dev-qa-db-ja.com

DATEまたはDATETIMEにデフォルト値を設定するとmysqlでエラーが発生する

私はMySqlサーバー5.7.11とこの文章を実行しています。

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

is動作していません。エラーを出す:

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

しかし、以下:

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

は動作します

DATEの場合も同じです。

サイドノートとして、 mysqlのドキュメント に記載されています。

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

彼らが言っても:

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

Mysqlドキュメントからの2番目の引用も考慮に入れて、それがなぜそのエラーを与えているのか誰かに私に知らせてもらえますか?

88
Evhz

このエラーは、最新の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を使うことは超特権を必要とし、それはその時から全てのクライアントが接続する操作に影響します

上記の方法でうまくいかない場合は、(ubuntuによる)/etc/mysql/my.cnfに行き、STRICT_TRANS_TABLESをコメントアウトしてください。

また、サーバの起動時にSQLモードを永続的に設定したい場合は、LinuxまたはMacOSのSET sql_mode=''my.cnfを含めます。 Windowsの場合、これはmy.iniファイルで行わなければなりません。

ただし、MYSQL 5.6では、厳密モードはデフォルトで有効になっていません。そのため、 MYSQL 6のドキュメントのようにエラーは発生しません

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

UPDATE

@ Dylan-Suが言ったバグの問題に関して:

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

しかし、私はNOW()関数に関する別の関連バグレポートを持っています

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

他の便利な注意事項[ 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では、このモードは推奨されていません。以前のバージョンでは、設定ファイルのそれぞれの行をコメントアウトする必要があります。 MySQL 5.7のNO_ZERO_DATEドキュメントを参照

159
geeksal

私は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のいずれかまたは両方が有効になっているモードを意味します。 のドキュメント には次のように書かれています。

msgstr "" "MySQL 5.7のデフォルトSQLモードにはこれらのモードが含まれます:ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES、NO_ZERO_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER、そしてNO_ENGINE_SUBSTITUTION

14
bg17aw

日付フィールドに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値(正しい日付であるかどうかにかかわらず)はこの日付より前のものであるためです。

4
Martin T.

設定構文の問題

MIXQLのいくつかのバージョン(テスト済み5.7。*)では* nixシステムの下であなたはこの構文を使うべきです:

[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モードのより完全なレビュー:

永続的なSql Modeフラグを設定する方法

4
Heroselohim

次の行を追加するだけです:sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

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

それからSudo service mysql restart

4

まず現在のセッションを選択します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 = '...';
3
simhumileco

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のための回帰バグです。

2
Dylan Su

この答えはMySQL 5.7用です。

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は実際にはこれらのパラメータと組み合わせで構成されていません。

1
stackdave
set global sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
0
Aris tri jaka

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

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

enter image description here

0
Vindic

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

Ubuntuの/etc/mysql/my.cnfで私の設定:

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