DATE veya DATETIME için varsayılan değeri ayarlarken MySQL'de hata


124

MySql Server 5.7.11 çalıştırıyorum ve bu cümle:

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

edilir değil çalışma. Hatayı vermek:

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

Ama şu:

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

sadece çalışır .

DATE için aynı durum.

Bir itibariyle sidenote , bu belirtilen MySQL docs :

TARİH türü, tarih bölümü olan ancak saat bölümü olmayan değerler için kullanılır. MySQL, TARİH değerlerini 'YYYY-AA-GG' biçiminde alır ve görüntüler. Desteklenen aralık "1000-01-01" ile "9999-12-31" arasındadır.

şöyle deseler bile:

Geçersiz DATE, DATETIME veya TIMESTAMP değerleri, uygun türün ('0000-00-00' veya '0000-00-00 00:00:00') “sıfır” değerine dönüştürülür.

MySQL belgelerinden ikinci alıntıyı da hesaba katarak, herhangi biri bana neden bu hatayı verdiğini söyleyebilir mi?


11
Açıkça anlamsız olan bir varsayılanı neden isteyesiniz? Tarih bilinmiyorsa, tam olarak NULLbunun için.
Tom H

Not olarak: Bu, SQL Fiddle - sqlfiddle.com/#!9/02c98 üzerinde 5.6 sürümünde çalışır .
Gordon Linoff

@Karlos güncellenmiş yanıtı kontrol edin.
geeksal

Yanıtlar:


209

Hata, en son MYSQL 5.7 belgelerine göre katı mod olabilen sql modundan kaynaklanmaktadır.

MySQL Belgeleri 5.7 diyor ki :

Katı mod, sunucunun geçerli bir tarih olarak '0000-00-00'e izin verip vermediğini etkiler: Katı mod etkin değilse,' 0000-00-00'e izin verilir ve eklemeler hiçbir uyarı üretmez. Katı mod etkinleştirilirse, '0000-00-00'e izin verilmez ve IGNORE da verilmediği sürece eklemeler bir hata oluşturur. INSERT IGNORE ve UPDATE IGNORE için, '0000-00-00'e izin verilir ve ekler bir uyarı oluşturur.

MYSQL modunu kontrol etmek için

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

STRICT_TRANS_TABLES modu devre dışı bırakılıyor

Ancak biçime izin vermek için 0000-00-00 00:00:00 mysql yapılandırma dosyasında veya komutla STRICT_TRANS_TABLES modunu devre dışı bırakmanız gerekir

Komutla

SET sql_mode = '';

veya

SET GLOBAL sql_mode = '';

Anahtar kelimeyi kullanmak GLOBALsüper öncelikler gerektirir ve o andan itibaren tüm istemcilerin bağlandığı işlemleri etkiler.

Yukarıdaki çalışmıyorsa, gidin /etc/mysql/my.cnf(ubuntu'ya göre) ve yorum yapınSTRICT_TRANS_TABLES

Kalıcı sunucu başlangıçta sql modunu ayarlamak istiyorsanız Ayrıca, ardından dahil SET sql_mode=''yılında my.cnfLinux veya MacOS üzerinde. Windows için bunun my.inidosyada yapılması gerekir .

Not

Ancak MYSQL 5.6'da varsayılan olarak katı mod etkinleştirilmemiştir. Bu yüzden başına hatayı üretmez MYSQL 6 belgelerine diyor

MySQL, "sahte tarih" olarak "0000-00-00" "sıfır" değerini kaydetmenize izin verir. Bu, bazı durumlarda NULL değerleri kullanmaktan daha uygundur ve daha az veri ve dizin alanı kullanır. '0000-00-00'e izin vermemek için NO_ZERO_DATE SQL modunu etkinleştirin.

GÜNCELLEME

@ Dylan-Su tarafından dediği gibi hata konusuyla ilgili olarak:

Bunun, ürünün daha da geliştirilmesine bağlı olarak bazı şeylerin değişmesi nedeniyle MYSQL'in zaman içinde gelişmesi gibi bir hata olduğunu sanmıyorum.

Ancak NOW()işlevle ilgili başka bir hata raporum var

Tarih ve saat alanı varsayılan ŞİMDİ kabul etmiyor ()

Başka Bir Yararlı not [bkz . TIMESTAMP ve DATETIME için Otomatik Başlatma ve Güncelleme ]

MySQL 5.6.5'ten itibaren, TIMESTAMP ve DATETIME sütunları otomatik olarak başlatılabilir ve geçerli tarih ve saate (yani, geçerli zaman damgasına) göre güncellenebilir. 5.6.5'ten önce, bu yalnızca TIMESTAMP ve tablo başına en fazla bir TIMESTAMP sütunu için geçerlidir. Aşağıdaki notlar önce MySQL 5.6.5 ve üstü için otomatik başlatma ve güncellemeyi, ardından 5.6.5'ten önceki sürümler için farklılıkları açıklar.

NO_ZERO_DATE İle İlgili Güncelleme

MySQL 5.7.4 itibariyle bu mod kullanımdan kaldırılmıştır. Önceki sürüm için, yapılandırma dosyasındaki ilgili satırı yorumlamanız gerekir. NO_ZERO_DATE tarihinde MySQL 5.7 belgelerine bakın


5
GÜNCELLEME IGNORE aradığım şey is🏻
Afanasii Kurakin

2
Yanlış. Ben STRICT_TRANS_TABLESbenim hem MySQL örnekleri, yerel ve sunucu için. Bununla birlikte, 0000-00-00yerel örneğime kolayca ekleyebiliyorum , ancak sunucu örneğimde yapamıyorum - hata atıldı. Neden? Çünkü sunucum MySQL yapılandırması NO_ZERO_DATEetkinleştirildi. Ve benim yerelde yok.
Green

ok @ Yeşil Mümkünse cevabı
bulup

4
Benim durumumda 'SET sql_mode = ""' çalışmadı. 'GLOBAL SET sql_mode = "";' işi benim için yaptı.
arjen Stens

Ayrıca NO_ZERO_DATEkaldırılmalıdır
Preshan Pradeepa

18

MySql 5.7.14 ile WAMP 3.0.6'da bu hatayı yaşadım.

Çözüm :

değişim hattı 70 içinde (sizin ini dosyası bakir ise) c:\wamp\bin\mysql\mysql5.7.14\my.inidosyanın

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

için

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

ve tüm hizmetleri yeniden başlatın.

Bu, katı modu devre dışı bırakacaktır. Belgelere göre, "katı mod", biri veya her ikisi ile STRICT_TRANS_TABLESveya STRICT_ALL_TABLESetkinleştirilmiş bir mod anlamına gelir . Dokümantasyon diyor ki:

"MySQL 5.7'deki varsayılan SQL modu şu modları içerir: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER ve NO_ENGINE_SUBSTITUTION."


14

Bir tarih alanı için verilerin NULL ile 0000-00-00 arasında karıştırıldığı bir duruma girdim. Ama '0000-00-00'ü NULL olarak nasıl güncelleyeceğimi bilmiyordum çünkü

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

artık izin verilmiyor. Çözümüm oldukça basitti:

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

çünkü tüm yanlış my_date_fielddeğerler (doğru tarihler olsun veya olmasın) bu tarihten önceydi.


2
Mükemmel hızlı çözüm. Aslında <'0000-01-01'geçerli bir tarih olduğu için de kullanabilirsiniz .
Ricky McMaster

5

Yapılandırma sözdizimi sorunu

MYSQL'in bazı sürümlerinde (5.7. * Test edildi) * nix sistemleri altında şu sözdizimini kullanmalısınız:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Bunlar işe yaramayacak:

tırnak yok

sql-mode=NO_ENGINE_SUBSTITUTION

tırnak yok altını çiz

sql_mode=NO_ENGINE_SUBSTITUTION

alt çizgi ve tırnak

sql_mode="NO_ENGINE_SUBSTITUTION"

Yapılandırma değerlerinin ve sql modunun daha eksiksiz bir incelemesi:

Kalıcı SQL Modu bayrakları nasıl kurulur


5

Önce mevcut oturumu seçin sql_mode:

SELECT @@SESSION.sql_mode;

Ardından bu varsayılan değer gibi bir şey elde edeceksiniz :

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

ve sonra sql_modeolmadan ayarlayın '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';

Hibeleriniz varsa, bunu aşağıdakiler için de yapabilirsiniz GLOBAL:

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

4

Sadece satırı ekleyin: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

dosya içi: /etc/mysql/mysql.conf.d/mysqld.cnf

sonra sudo service mysql restart


1
5.7.23 için çalışıyor.
user2513149

1
Muhtemelen SELECT @@SESSION.sql_mode;önce size verdiklerinden NO_ZERO_IN_DATE, NO_ZERO_DATE ve STRICT_TRANS_TABLES’leri kaldırmalarını öneririm. Bu şekilde, etkinleştirdiğiniz diğer ayarları korursunuz. Sql modum için ayarlanan bu iki öğeden çok daha fazlasına sahiptim. Hepsinin ne yaptığını bilmiyorum ama bu noktada onları kaldırma riskini almak istemiyorum.
Radley Sustaire

2

5.7.8 için çalışıyor:

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)

Sorununuzu yeniden oluşturmak için bir SQLFiddle oluşturabilirsiniz.

http://sqlfiddle.com/

MySQL 5.6 ve 5.7.8 için çalışıyor ancak 5.7.11'de başarısız oluyorsa. O zaman muhtemelen 5.7.11 için bir gerileme hatası olacaktır.


1

Problemi MySQL Workbench ile çözmek için (Çözümü sunucu tarafında uyguladıktan sonra):

Tercihler panelinde SQL_MODE öğesini TRADITIONAL olarak kaldırın.

görüntü açıklamasını buraya girin


1

Bu cevap sadece MySQL 5.7 içindir:

En iyisi, sql_mode'da gerçekten boş olarak ayarlanmamıştır, bunun yerine PHP'de bir oturum değişkenini kullanın:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Yani en azından başka bir varsayılan değerleri korursunuz.

Mysql belgelerinin net olmaması çılgınca, bu yenilgi değerlerini sql_mode'da silmeniz gerekiyor:

NO_ZERO_IN_DATE, NO_ZERO_DATE, anlıyorum, ancak gelecek sürümlerde bu artık kullanılmayacak.

STRICT_ALL_TABLES, bununla, parametrelerin yok sayılmasından önce, onu da silmeniz gerekir.

Son olarak da GELENEKTİR, ancak dokümantasyon bu parametre hakkında konuşur: bir sütuna yanlış bir değer eklerken "uyarı yerine hata verin" ", bu parametre ile sıfır değerli tarihler girilmez, ancak evet yoktur.

MySQL, bu parametreler ve kombinasyonlarla gerçekten organize edilmemiştir.


0

İçin seçenek kombinasyonları mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64) .

Atmaz:

STRICT_TRANS_TABLES + NO_ZERO_DATE

atar:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

/etc/mysql/my.cnfUbuntu'daki ayarlarım :

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

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

0

Zorlayıcı xamp / mysql / bin "my.ini" dosyasını açın ve satırı değiştirin: Sql_node for ->

"Sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

"NO_ZERO_IN_DATE" öğesini KALDIR


Stackoverflow'a hoş geldiniz, cevabın okunaklılığını artırmak için lütfen doğru kod biçimlendirmesini kullanın.
vlizana
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.