Kesalahan di MySQL saat menyetel nilai default untuk DATE atau DATETIME

124

Saya menjalankan MySql Server 5.7.11 dan kalimat ini:

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

adalah tidak bekerja. Memberikan kesalahan:

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

Tapi berikut ini:

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

hanya bekerja .

Kasus yang sama untuk DATE.

Sebagai catatan samping , ini disebutkan dalam dokumen MySQL :

Jenis DATE digunakan untuk nilai dengan bagian tanggal tetapi tidak ada bagian waktu. MySQL mengambil dan menampilkan nilai DATE dalam format 'YYYY-MM-DD'. Rentang yang didukung adalah '1000-01-01' hingga '9999-12-31'.

bahkan jika mereka juga mengatakan:

Nilai DATE, DATETIME, atau TIMESTAMP tidak valid diubah ke nilai "nol" dari jenis yang sesuai ('0000-00-00' atau '0000-00-00 00:00:00').

Setelah juga memperhitungkan kutipan kedua dari dokumentasi MySQL, adakah yang bisa memberi tahu saya mengapa itu memberikan kesalahan itu?

Evhz
sumber
11
Mengapa Anda menginginkan default yang jelas tidak ada artinya? Jika tanggalnya tidak diketahui maka untuk itulah tepatnya NULL.
Tom H
Sebagai catatan: Ini berfungsi di versi 5.6 di SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Gordon Linoff
@Karlos memeriksa jawaban yang diperbarui.
geeksal

Jawaban:

209

Kesalahannya karena mode sql yang dapat menjadi mode ketat sesuai dokumentasi MYSQL 5.7 terbaru

Dokumentasi MySQL 5.7 mengatakan :

Mode ketat memengaruhi apakah server mengizinkan '0000-00-00' sebagai tanggal yang valid: Jika mode ketat tidak diaktifkan, '0000-00-00' diizinkan dan penyisipan tidak menghasilkan peringatan. Jika mode ketat diaktifkan, '0000-00-00' tidak diizinkan dan sisipan menghasilkan kesalahan, kecuali IGNORE diberikan juga. Untuk INSERT IGNORE dan UPDATE IGNORE, '0000-00-00' diizinkan dan sisipan menghasilkan peringatan.

Untuk memeriksa mode MYSQL

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

Menonaktifkan mode STRICT_TRANS_TABLES

Namun untuk mengizinkan format 0000-00-00 00:00:00Anda harus menonaktifkan mode STRICT_TRANS_TABLES di file konfigurasi mysql atau dengan perintah

Dengan perintah

SET sql_mode = '';

atau

SET GLOBAL sql_mode = '';

Menggunakan kata kunci GLOBALmembutuhkan super previliges dan itu mempengaruhi operasi yang terhubung dengan semua klien sejak saat itu

jika di atas tidak berfungsi daripada pergi ke /etc/mysql/my.cnf(sesuai ubuntu) dan beri komentarSTRICT_TRANS_TABLES

Juga, jika Anda ingin mengatur mode sql secara permanen saat startup server, sertakan SET sql_mode=''di my.cnfLinux atau MacOS. Untuk windows ini harus dilakukan dalam my.inifile.

Catatan

Namun mode ketat tidak diaktifkan secara default di MYSQL 5.6. Oleh karena itu tidak menghasilkan kesalahan sesuai dokumentasi MYSQL 6 yang mengatakan

MySQL mengizinkan Anda menyimpan nilai "nol" dari '0000-00-00' sebagai "tanggal palsu". Ini dalam beberapa kasus lebih nyaman daripada menggunakan nilai NULL, dan menggunakan lebih sedikit data dan ruang indeks. Untuk melarang '0000-00-00', aktifkan mode SQL NO_ZERO_DATE.

MEMPERBARUI

Mengenai masalah bug seperti yang dikatakan oleh @ Dylan-Su:

Saya tidak berpikir ini adalah bug karena cara MYSQL berevolusi dari waktu ke waktu karena beberapa hal diubah berdasarkan peningkatan produk lebih lanjut.

Namun saya memiliki laporan bug terkait lainnya terkait NOW()fungsi tersebut

Bidang tanggal waktu tidak menerima default SEKARANG ()

Catatan Berguna lainnya [lihat Inisialisasi dan Pembaruan Otomatis untuk TIMESTAMP dan DATETIME ]

Pada MySQL 5.6.5, kolom TIMESTAMP dan DATETIME dapat diinisialisasi dan diperbarui secara otomatis ke tanggal dan waktu saat ini (yaitu, stempel waktu saat ini). Sebelum 5.6.5, ini hanya berlaku untuk TIMESTAMP, dan paling banyak untuk satu kolom TIMESTAMP per tabel. Catatan berikut pertama-tama menjelaskan inisialisasi dan pembaruan otomatis untuk MySQL 5.6.5 dan yang lebih baru, kemudian perbedaan untuk versi sebelum 5.6.5.

Pembaruan Mengenai NO_ZERO_DATE

Pada MySQL mulai 5.7.4, mode ini sudah tidak digunakan lagi. Untuk versi sebelumnya Anda harus mengomentari baris masing-masing di file konfigurasi. Lihat dokumentasi MySQL 5.7 pada NO_ZERO_DATE

geeksal
sumber
5
UPDATE IGNORE adalah apa yang saya cari 👍🏻
Afanasii Kurakin
2
Salah. Saya memiliki STRICT_TRANS_TABLESuntuk kedua instance MySQL saya, lokal dan server. Namun, saya dapat dengan mudah memasukkan 0000-00-00dalam contoh lokal saya, tetapi tidak dapat dalam contoh server saya - kesalahan dilemparkan. Mengapa? Karena konfigurasi MySQL server saya telah NO_ZERO_DATEdiaktifkan. Dan orang lokal saya tidak memilikinya.
Hijau
ok @Green Saya akan mencari tahu dan memperbarui jawabannya jika berlaku
geeksal
4
Dalam kasus saya 'SET sql_mode = ""' tidak berfungsi. 'SET GLOBAL sql_mode = "";' melakukan pekerjaan untuk saya.
arjen Stens
Juga NO_ZERO_DATEharus dihapus
Preshan Pradeepa
18

Saya mengalami kesalahan ini dengan WAMP 3.0.6 dengan MySql 5.7.14.

Solusi :

ubah baris 70 (jika file ini tidak tersentuh) di c:\wamp\bin\mysql\mysql5.7.14\my.inifile dari

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

untuk

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

dan mulai ulang semua layanan.

Ini akan menonaktifkan mode ketat. Sesuai dokumentasi, "mode ketat" berarti mode dengan salah satu atau keduanya STRICT_TRANS_TABLESatau STRICT_ALL_TABLESdiaktifkan. The dokumentasi mengatakan:

"Mode SQL default di MySQL 5.7 mencakup mode berikut: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, dan NO_ENGINE_SUBSTITUTION."

bg17aw.dll
sumber
14

Saya mendapat situasi di mana data dicampur antara NULL dan 0000-00-00 untuk bidang tanggal. Tapi saya tidak tahu bagaimana mengupdate '0000-00-00' menjadi NULL, karena

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

tidak diperbolehkan lagi. Solusi saya cukup sederhana:

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

karena semua nilai yang salah my_date_field(apakah tanggal yang benar atau tidak) berasal dari sebelum tanggal ini.

Martin T.
sumber
2
Solusi cepat yang sempurna. Anda sebenarnya juga bisa menggunakan <'0000-01-01'karena itu tentu saja tanggal yang valid.
Ricky McMaster
5

Masalah sintaks konfigurasi

Pada beberapa versi MYSQL (diuji 5.7. *) Di bawah sistem * nix Anda harus menggunakan sintaks ini:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Ini tidak akan berhasil:

tanda hubung tanpa tanda kutip

sql-mode=NO_ENGINE_SUBSTITUTION

garis bawahi tanpa tanda kutip

sql_mode=NO_ENGINE_SUBSTITUTION

garis bawah dan tanda kutip

sql_mode="NO_ENGINE_SUBSTITUTION"

Tinjauan yang lebih lengkap tentang nilai konfigurasi dan mode sql:

Cara menyiapkan tanda Mode Sql permanen

Heroselohim
sumber
5

Pertama pilih sesi saat ini sql_mode:

SELECT @@SESSION.sql_mode;

Kemudian Anda akan mendapatkan nilai default seperti itu :

'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'

lalu setel sql_modetanpa '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';

Jika Anda memiliki hibah, Anda dapat melakukannya juga untuk GLOBAL:

SELECT @@GLOBAL.sql_mode;
SET GLOBAL sql_mode = '...';
simhumileco.dll
sumber
4

Cukup tambahkan baris: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

file di dalam: /etc/mysql/mysql.conf.d/mysqld.cnf

kemudian sudo service mysql restart

ferreidon aftahi
sumber
1
Bekerja untuk 5.7.23.
user2513149
1
Saya mungkin akan menyarankan SELECT @@SESSION.sql_mode;pertama, dan mereka menghapus NO_ZERO_IN_DATE, NO_ZERO_DATE, dan STRICT_TRANS_TABLES dari apa yang diberikannya kepada Anda. Dengan cara itu Anda menyimpan pengaturan lain apa pun yang telah Anda aktifkan. Saya memiliki lebih dari sekadar dua item yang ditetapkan untuk mode sql saya. Tidak tahu apa yang mereka semua lakukan, tetapi saya tidak ingin mengambil risiko menghapus mereka pada saat ini.
Radley Sustaire
2

Ini bekerja untuk 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)

Anda dapat membuat SQLFiddle untuk membuat ulang masalah Anda.

http://sqlfiddle.com/

Jika berfungsi untuk MySQL 5.6 dan 5.7.8, tetapi gagal pada 5.7.11. Maka itu mungkin bug regresi untuk 5.7.11.

Dylan Su
sumber
1

Untuk mengatasi masalah dengan MySQL Workbench (Setelah menerapkan solusi di sisi server):

Hapus SQL_MODE ke TRADITIONAL di panel preferensi.

masukkan deskripsi gambar di sini

Vindic
sumber
1

Jawaban ini hanya untuk MySQL 5.7:

Best tidak benar-benar mengosongkan sql_mode, sebagai gantinya gunakan variabel sesi dalam PHP dengan:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Jadi setidaknya Anda menyimpan nilai default lainnya.

Sungguh gila dokumentasi mysql tidak jelas, Anda perlu menghapus nilai defeault ini di sql_mode:

NO_ZERO_IN_DATE, NO_ZERO_DATE, saya mengerti, tetapi di versi mendatang hal ini akan dihentikan.

STRICT_ALL_TABLES, dengan ini, sebelum parameter diabaikan, jadi Anda perlu menghapusnya juga.

Akhirnya TRADISIONAL juga, tetapi dokumentasi berbicara tentang parameter ini: "berikan kesalahan alih-alih peringatan" saat memasukkan nilai yang salah ke dalam kolom ", dengan parameter ini, tanggal dengan nilai nol tidak dimasukkan, tetapi tanpa ya.

MySQL tidak benar-benar diatur dengan parameter dan kombinasi ini.

stackdave
sumber
0

Kombinasi opsi untuk mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64).

Tidak melempar:

STRICT_TRANS_TABLES + NO_ZERO_DATE

Melempar:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

Pengaturan saya di /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"
hijau
sumber
0
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';
Aris tri jaka
sumber
0

Di direktori xamp / mysql / bin Buka "my.ini" dan ganti baris: Sql_node for ->

"sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

HAPUS "NO_ZERO_IN_DATE"

leandro ramos
sumber
Selamat datang di stackoverflow, harap gunakan pemformatan kode yang benar untuk meningkatkan keterbacaan jawaban.
vlizana