เกิดข้อผิดพลาดใน 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

ในฐานะที่เป็นsidenoteมีการกล่าวถึงในเอกสาร 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 ใครช่วยแจ้งให้เราทราบว่าเหตุใดจึงให้ข้อผิดพลาดนั้น


11
ทำไมคุณถึงต้องการค่าเริ่มต้นที่ไม่มีความหมายอย่างเห็นได้ชัด? หากไม่ทราบวันที่แสดงว่าNULLมีไว้เพื่ออะไร
Tom H

เป็นบันทึก: นี้ทำงานในรุ่น 5.6 ใน SQL ซอ - sqlfiddle.com/#!9/02c98
Gordon Linoff

@Karlos ตรวจสอบคำตอบที่อัปเดต
geeksal

คำตอบ:


209

ข้อผิดพลาดเกิดจากโหมด sql ซึ่งอาจเป็นโหมดที่เข้มงวดตามเอกสาร MYSQL 5.7 ล่าสุด

เอกสาร MySQL 5.7 พูดว่า :

โหมดเข้มงวดจะส่งผลต่อว่าเซิร์ฟเวอร์อนุญาตให้ "0000-00-00" เป็นวันที่ที่ถูกต้องหรือไม่: หากไม่ได้เปิดใช้งานโหมดเข้มงวดจะอนุญาตให้ใช้ "0000-00-00" และการแทรกจะไม่มีคำเตือน หากเปิดใช้งานโหมดเข้มงวด "0000-00-00" จะไม่ได้รับอนุญาตและการแทรกจะก่อให้เกิดข้อผิดพลาดเว้นแต่จะได้รับ IGNORE ด้วย สำหรับ 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คุณต้องปิดใช้งานโหมด STRICT_TRANS_TABLES ในไฟล์ config mysql หรือตามคำสั่ง

ตามคำสั่ง

SET sql_mode = '';

หรือ

SET GLOBAL sql_mode = '';

การใช้คีย์เวิร์ดนั้นGLOBALต้องการ super previliges และมีผลต่อการดำเนินการที่ไคลเอนต์ทั้งหมดเชื่อมต่อตั้งแต่นั้นเป็นต้นมา

หากข้างต้นใช้งานไม่ได้ให้ไปที่/etc/mysql/my.cnf(ตาม ubuntu) และแสดงความคิดเห็นSTRICT_TRANS_TABLES

นอกจากนี้หากคุณต้องการตั้งค่าโหมด sql อย่างถาวรเมื่อเริ่มต้นเซิร์ฟเวอร์ให้รวมSET sql_mode=''ไว้my.cnfใน Linux หรือ MacOS สำหรับ windows สิ่งนี้ต้องทำในmy.iniไฟล์

บันทึก

อย่างไรก็ตามโหมดเข้มงวดไม่ได้เปิดใช้งานโดยค่าเริ่มต้นใน MYSQL 5.6 ดังนั้นจึงไม่เกิดข้อผิดพลาดตามเอกสารของ MYSQL 6ซึ่งระบุว่า

MySQL อนุญาตให้คุณจัดเก็บค่า "ศูนย์" ของ "0000-00-00" เป็น "วันที่จำลอง" ในบางกรณีสะดวกกว่าการใช้ค่า NULL และใช้พื้นที่ข้อมูลและดัชนีน้อยกว่า หากต้องการไม่อนุญาต "0000-00-00" ให้เปิดใช้งานโหมด SQL NO_ZERO_DATE

UPDATE

เกี่ยวกับปัญหาดังกล่าวโดย @ Dylan-Su:

ฉันไม่คิดว่านี่เป็นข้อผิดพลาดเนื่องจากวิธีการที่ MYSQL มีการพัฒนาตลอดเวลาเนื่องจากมีการเปลี่ยนแปลงบางอย่างตามการปรับปรุงเพิ่มเติมของผลิตภัณฑ์

อย่างไรก็ตามฉันมีรายงานข้อบกพร่องอื่นที่เกี่ยวข้องเกี่ยวกับNOW()ฟังก์ชันนี้

ฟิลด์ Datetime ไม่ยอมรับค่าเริ่มต้น NOW ()

หมายเหตุที่เป็นประโยชน์อีกประการหนึ่ง [ดูการเริ่มต้นอัตโนมัติและการอัปเดตสำหรับ TIMESTAMP และ DATETIME ]

ตั้งแต่ MySQL 5.6.5 คอลัมน์ TIMESTAMP และ DATETIME สามารถเริ่มต้นโดยอัตโนมัติและอัปเดตเป็นวันที่และเวลาปัจจุบัน (นั่นคือการประทับเวลาปัจจุบัน) ก่อน 5.6.5 นี่เป็นจริงสำหรับ TIMESTAMP เท่านั้นและสำหรับ TIMESTAMP มากที่สุดหนึ่งคอลัมน์ต่อตาราง หมายเหตุต่อไปนี้จะอธิบายถึงการเริ่มต้นอัตโนมัติและการอัปเดตสำหรับ MySQL 5.6.5 ขึ้นไปก่อนจากนั้นข้อแตกต่างสำหรับเวอร์ชันก่อนหน้า 5.6.5

อัปเดตเกี่ยวกับวันที่ NO_ZERO_DATE

เนื่องจาก MySQL ณ 5.7.4 โหมดนี้เลิกใช้งานแล้ว สำหรับเวอร์ชันก่อนหน้าคุณต้องแสดงความคิดเห็นในบรรทัดที่เกี่ยวข้องในไฟล์กำหนดค่า อ้างอิงเอกสาร MySQL 5.7 ในวันที่ NO_ZERO_DATE


5
UPDATE IGNORE คือสิ่งที่ฉันกำลังมองหา👍🏻
Afanasii Kurakin

2
ไม่ถูกต้อง. ฉันมีSTRICT_TRANS_TABLESทั้งอินสแตนซ์ MySQL โลคัลและเซิร์ฟเวอร์ อย่างไรก็ตามฉันสามารถแทรก0000-00-00อินสแตนซ์ในเครื่องของฉันได้อย่างง่ายดายแต่ไม่สามารถอยู่ในอินสแตนซ์เซิร์ฟเวอร์ของฉันได้ - เกิดข้อผิดพลาด ทำไม? เนื่องจากเซิร์ฟเวอร์ MySQL config ได้NO_ZERO_DATEเปิดใช้งาน และท้องถิ่นของฉันไม่มี
กรีน

ok @Green ฉันจะหาและอัปเดตคำตอบหากมี
geeksal

4
ในกรณีของฉัน 'SET sql_mode = ""' ไม่ทำงาน 'SET GLOBAL sql_mode = ""; ทำงานให้ฉัน
arjen Stens

นอกจากนี้ยังNO_ZERO_DATEควรจะออก
Preshan Pradeepa

18

ฉันมีข้อผิดพลาดนี้กับ WAMP 3.0.6 พร้อม MySql 5.7.14

วิธีแก้ไข :

เปลี่ยนบรรทัด 70 (หากไฟล์ ini ของคุณไม่ถูกแตะต้อง) ใน c:\wamp\bin\mysql\mysql5.7.14\my.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เปิดใช้งาน เอกสารพูดว่า:

"โหมด SQL เริ่มต้นใน MySQL 5.7 ประกอบด้วยโหมดเหล่านี้: 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'เนื่องจากเป็นวันที่ที่ถูกต้อง
Ricky McMaster

5

กำหนดค่าไวยากรณ์ปัญหา

ใน MYSQL บางเวอร์ชัน (ทดสอบ 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 แบบถาวร


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

1
ฉันอาจจะแนะนำ SELECT @@SESSION.sql_mode;ก่อนและพวกเขาจะลบ NO_ZERO_IN_DATE, NO_ZERO_DATE และ STRICT_TRANS_TABLES ออกจากสิ่งที่ให้คุณ ด้วยวิธีนี้คุณจะเก็บการตั้งค่าอื่น ๆ ที่คุณเปิดใช้งานไว้ ฉันมีมากกว่าสองรายการที่ตั้งค่าไว้สำหรับโหมด sql ของฉัน ไม่รู้ว่าพวกเขาทั้งหมดทำอะไร แต่ฉันไม่ต้องการเสี่ยงที่จะลบพวกเขาในตอนนี้
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:

ดีที่สุดไม่ได้ตั้งค่าให้ sql_mode ว่างเปล่าแทนที่จะใช้ใน PHP ตัวแปรเซสชันกับ:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

อย่างน้อยคุณก็เก็บค่าเริ่มต้นอื่นไว้

มันบ้ามากที่เอกสาร mysql ไม่ชัดเจนคุณต้องลบค่า Default นี้ใน 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

ใน Diretory xamp / mysql / bin เปิด "my.ini" และเปลี่ยนบรรทัด: Sql_node สำหรับ ->

"sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

ลบ "NO_ZERO_IN_DATE"


ยินดีต้อนรับสู่ stackoverflow โปรดใช้การจัดรูปแบบรหัสที่เหมาะสมเพื่อปรับปรุงความชัดเจนของคำตอบ
vlizana
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.