เหตุใดคอลัมน์ข้อความจึงไม่มีค่าเริ่มต้นใน MySQL


184

หากคุณพยายามสร้างคอลัมน์ TEXT บนโต๊ะและให้เป็นค่าเริ่มต้นใน MySQL คุณจะได้รับข้อผิดพลาด (อย่างน้อย Windows) ฉันไม่เห็นเหตุผลที่คอลัมน์ข้อความไม่ควรมีค่าเริ่มต้น ไม่มีคำอธิบายใด ๆ จากเอกสาร MySQL ดูเหมือนไม่มีเหตุผลสำหรับฉัน (และค่อนข้างน่าผิดหวังเพราะฉันต้องการค่าเริ่มต้น!) มีใครรู้บ้างว่าทำไมจึงไม่อนุญาต


1
เราเห็นข้อความค้นหาที่คุณใช้หรือไม่
Robert

2
คุณแน่ใจหรือไม่ว่าต้องการคอลัมน์ TEXT ไม่ใช่ VARCHAR ใช่ไหม TEXT Column ใช้สำหรับสิ่งที่ยาวเกิน 255 ไบต์
scy

5
นี่ควรเป็นความคิดเห็น นอกจากนี้ใช่เขาหมายความว่าTEXT- คอลัมน์เหล่านั้นไม่สามารถมีค่าเริ่มต้นได้ VARCHARสามารถ.
Pekka

1
หากคุณใช้ phpmyadmin เพื่อตั้งค่าฐานข้อมูลของคุณอาจต้องการตรวจสอบ mysql gui tools / workbench ... ;)
dmp

1
ใช่ฉันต้องการตัวละครมากกว่า 255 ตัว
รัส

คำตอบ:


92

Windows MySQL v5 มีข้อผิดพลาดเกิดขึ้น แต่ Linux และเวอร์ชันอื่น ๆ จะแจ้งเตือนเท่านั้น สิ่งนี้จะต้องได้รับการแก้ไข WTF?

ดูความพยายามที่จะแก้ไขข้อผิดพลาด # 19498 ใน MySQL Bugtracker:

Bryce Nesbitt เมื่อวันที่ 4 เมษายน 2008 เวลา 16:36 น.:
บน MS Windows กฎ "no DEFAULT" เป็นข้อผิดพลาดขณะที่บนแพลตฟอร์มอื่น ๆ มักจะเป็นคำเตือน แม้ว่าจะไม่ใช่จุดบกพร่อง แต่ก็เป็นไปได้ที่จะติดกับสิ่งนี้หากคุณเขียนโค้ดบนแพลตฟอร์มแบบผ่อนปรนและเรียกใช้ในภายหลังบนแพลตฟอร์มที่เข้มงวด:

โดยส่วนตัวฉันคิดว่านี่เป็นข้อผิดพลาด การค้นหา "คอลัมน์ BLOB / TEXT ไม่สามารถมีค่าเริ่มต้น" ส่งคืนผลลัพธ์ประมาณ 2,940 รายการใน Google ส่วนใหญ่เป็นรายงานความเข้ากันไม่ได้เมื่อพยายามติดตั้งสคริปต์ DB ที่ทำงานบนระบบเดียว แต่ไม่ใช่ระบบอื่น

ฉันพบปัญหาเดียวกันตอนนี้บนเว็บแอพที่ฉันกำลังแก้ไขสำหรับลูกค้าของฉันซึ่งเดิมติดตั้งบน Linux MySQL v5.0.83-log ฉันใช้ Windows MySQL v5.1.41 แม้พยายามใช้ phpMyAdmin เวอร์ชันล่าสุดเพื่อแยกฐานข้อมูล แต่ก็ไม่รายงานค่าเริ่มต้นสำหรับคอลัมน์ข้อความที่เป็นปัญหา แต่เมื่อฉันลองเรียกใช้การแทรกบน Windows (ใช้งานได้ดีกับการปรับใช้ Linux) ฉันได้รับข้อผิดพลาดในคอลัมน์ ABC ฉันพยายามสร้างตารางในเครื่องใหม่โดยใช้ค่าเริ่มต้นที่ชัดเจน (ขึ้นอยู่กับการเลือกค่าที่ไม่ซ้ำสำหรับคอลัมน์นั้น) และท้ายที่สุดได้รับคอลัมน์ BLOB / TEXT ที่มีประโยชน์และไม่สามารถมีค่าเริ่มต้นได้

อีกครั้งการไม่รักษาความเข้ากันได้พื้นฐานข้ามแพลตฟอร์มนั้นไม่เป็นที่ยอมรับและเป็นจุดบกพร่อง


วิธีปิดการใช้งานโหมดเข้มงวดใน MySQL 5 (Windows):

  • แก้ไข /my.ini และค้นหาบรรทัด

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • แทนที่ด้วย

    sql_mode='MYSQL40'
  • เริ่มบริการ MySQL ใหม่ (สมมติว่าเป็น mysql5)

    net stop mysql5
    net start mysql5

หากคุณมีสิทธิ์การเข้าถึงรูต / ผู้ดูแลระบบคุณอาจสามารถดำเนินการได้

mysql_query("SET @@global.sql_mode='MYSQL40'");

3
หากคุณมีสิทธิ์เข้าถึงรูทและใช้งาน phpMyAdmin ให้ไปที่หน้าหลัก (คลิกที่โลโก้ phpMyAdmin) ไปที่แท็บตัวแปรค้นหาตัวแปร sql_mode แล้วคลิกแก้ไข
Gavin

1
ฉันใช้ CentOS 5.8 และ MySQL v 14.14 Distrib 5.1.71 พ่นข้อผิดพลาดแทนที่จะเป็นคำเตือนเมื่อพยายามตั้งค่าเริ่มต้นเป็นเขตข้อมูล TEXT เพียงแค่ต้องการแจ้งให้ทราบว่ามันไม่ทำงานบนทุกแพลตฟอร์ม Linux
อเล็กซ์

OS X ที่เกรงว่าจะเกิดข้อผิดพลาดในวันนี้ เอกสารdev.mysql.com/doc/refman/5.7/en/blob.htmlพูดว่า "คอลัมน์ BLOB และ TEXT ไม่สามารถมีค่าเริ่มต้น" FWIW (แต่ไม่ใช่เหตุผล)
rogerdpack

31

หากไม่มีความรู้อย่างลึกซึ้งเกี่ยวกับเอ็นจิ้น mySQL ฉันจะบอกว่านี่เป็นกลยุทธ์การประหยัดหน่วยความจำ ฉันถือว่าเหตุผลอยู่หลังย่อหน้านี้จากเอกสาร :

แต่ละค่า BLOB หรือ TEXT จะแสดงภายในโดยวัตถุที่จัดสรรแยกต่างหาก นี่คือตรงกันข้ามกับชนิดข้อมูลอื่น ๆ ทั้งหมดซึ่งการจัดเก็บข้อมูลที่ถูกจัดสรรหนึ่งครั้งต่อคอลัมน์เมื่อเปิดตาราง

ดูเหมือนว่าการกรอกข้อมูลล่วงหน้าประเภทคอลัมน์เหล่านี้จะนำไปสู่การใช้หน่วยความจำและการลงโทษประสิทธิภาพ


5
-1: การจัดเก็บข้อมูลเช่นชื่อเมืองในคอลัมน์ TEXT จริง ๆ แล้วใช้หน่วยความจำทั้งหมดน้อยกว่าการจัดเก็บข้อมูลเดียวกันในคอลัมน์ CHAR หรือ VARCHAR
David Cary

5
@david คู่มือบทที่ฉันอ้างไม่ได้เกี่ยวกับการจัดเก็บ แต่การดึง
Pekka

1
ฉันไม่เห็นว่าจะนำไปสู่การใช้หน่วยความจำผิดปกติและการลงโทษประสิทธิภาพอย่างไร เห็นได้ชัดว่าเมื่อผู้ใช้กำหนดค่าเริ่มต้นเขาคาดว่าผลการดำเนินงานไม่ว่าจะเป็นประเภทข้อมูลใด อย่างไรก็ตามเท่าที่ฉันเข้าใจว่าคุณระบุว่าสำหรับเขตข้อมูล BLOB / TEXT การเข้าชมนี้มีประสิทธิภาพค่อนข้างสูงเมื่อเทียบกับประเภทข้อมูลอื่น ๆ และเกี่ยวข้องกับความจริงที่ว่า BLOB / TEXT ถูกเก็บไว้ภายในเป็นวัตถุที่แยกกันอย่างไร นี่ไม่สมเหตุสมผลเลยสำหรับฉัน
ประหลาด

27
IMHO มันไม่ใช่กลยุทธ์การประหยัดหน่วยความจำ มันอาจเป็นข้อบกพร่องหรือคนที่เขียนมันเสียสติ และฉันคิดว่ามันเป็นรุ่นหลังเพราะพวกเขาไม่สามารถแก้ไขได้อย่างน้อย 8 ปีในขณะนี้ ฟังก์ชั่นพื้นฐานที่ฐานข้อมูลอื่น ๆ มี
ประหลาด

2
ไม่สำคัญว่าควรเป็นตัวเลือกสำหรับผู้ที่ต้องการใช้งาน
jurchiks

15

คุณสามารถได้รับผลเช่นเดียวกับค่าเริ่มต้นโดยใช้ทริกเกอร์

create table my_text

(
   abc text
);

delimiter //
create trigger mytext_trigger before insert on my_text
for each row
begin
   if (NEW.abc is null ) then
      set NEW.abc = 'default text';
   end if;
end
//
delimiter ;

14

ในฐานะที่เป็นคำถามหลัก:

มีใครรู้บ้างว่าทำไมจึงไม่อนุญาต

ยังไม่ได้ตอบฉันทำการค้นหาอย่างรวดเร็วและพบการเพิ่มที่ค่อนข้างใหม่จากนักพัฒนาMySQLที่MySQL Bugs :

[17 มี.ค. 2017 15:11] Ståle Deraas

โพสต์โดยผู้พัฒนา:

นี่เป็นคำขอคุณลักษณะที่ถูกต้องและเมื่อเห็นอย่างรวดเร็วในครั้งแรกมันอาจดูไม่สำคัญที่จะเพิ่ม แต่ค่า TEXT / BLOBS จะไม่ถูกเก็บไว้โดยตรงในบัฟเฟอร์บันทึกที่ใช้สำหรับการอ่าน / การปรับปรุงตาราง ดังนั้นจึงซับซ้อนกว่าเล็กน้อยในการกำหนดค่าเริ่มต้นสำหรับพวกเขา

นี่ไม่ใช่คำตอบที่ชัดเจน แต่อย่างน้อยก็เป็นจุดเริ่มต้นสำหรับคำถามที่ว่าทำไม

ในเวลานั้นฉันจะเขียนโค้ดรอบ ๆ และทำให้คอลัมน์เป็นโมฆะหรือกำหนดค่า (เริ่มต้น'') ให้ชัดเจนสำหรับแต่ละinsertแอปพลิเคชันจากรหัส ...


13

"การสนับสนุนสำหรับการเริ่มต้นในข้อความคอลัมน์ / หยด" เป็น คำขอคุณสมบัติใน MySQL เซ (bug # 21532)

ฉันเห็นว่าฉันไม่ใช่คนเดียวที่ต้องการใส่ค่าเริ่มต้นในคอลัมน์ TEXT ฉันคิดว่าคุณสมบัตินี้ควรได้รับการสนับสนุนใน MySQL รุ่นที่ใหม่กว่า

สิ่งนี้ไม่สามารถแก้ไขได้ใน MySQL เวอร์ชัน 5.0 เพราะดูเหมือนว่ามันจะทำให้เกิดความไม่ลงรอยกันและดาต้ารอสหากใครก็ตามที่พยายามถ่ายโอนฐานข้อมูลไปมาระหว่างฐานข้อมูล (ปัจจุบัน) ที่ไม่รองรับคุณสมบัตินั้นและฐานข้อมูลใด ๆ ที่ไม่รองรับ คุณสมบัตินั้น


ดูเหมือนว่าคุณควรจะสามารถเปลี่ยนระหว่าง "" และ NULL สำหรับคอลัมน์ TEXT ที่อนุญาตให้มีค่าว่างได้ ดูเหมือนเป็นไปไม่ได้ที่จะทำ
phpguru

6

ปกติฉันใช้งานเว็บไซต์บน Linux แต่ฉันก็พัฒนาบนเครื่อง Windows ในพื้นที่ ฉันพบปัญหานี้หลายครั้งและเพิ่งแก้ไขตารางเมื่อฉันพบปัญหา ฉันติดตั้งแอพเมื่อวานนี้เพื่อช่วยให้ใครบางคนออกนอกเส้นทางและพบปัญหาอีกครั้ง ดังนั้นฉันจึงตัดสินใจว่าถึงเวลาที่จะคิดว่าเกิดอะไรขึ้น - และพบกระทู้นี้ ฉันไม่ชอบความคิดที่จะเปลี่ยน sql_mode ของเซิร์ฟเวอร์เป็นโหมดก่อนหน้า (โดยค่าเริ่มต้น) ดังนั้นฉันจึงคิดวิธีแก้ปัญหาง่ายๆ (ฉันคิดว่า)

แน่นอนว่าโซลูชันนี้ต้องการให้นักพัฒนาห่อสคริปต์สร้างตารางเพื่อชดเชยปัญหา MySQL ที่ทำงานบน Windows คุณจะเห็นแนวคิดที่คล้ายกันในไฟล์ดัมพ์ ข้อแม้หนึ่งข้อใหญ่คือสิ่งนี้อาจเป็นสาเหตุของปัญหาได้หากใช้การแบ่งพาร์ติชัน

// Store the current sql_mode
mysql_query("set @orig_mode = @@global.sql_mode");

// Set sql_mode to one that won't trigger errors...
mysql_query('set @@global.sql_mode = "MYSQL40"');

/**
 * Do table creations here...
 */

// Change it back to original sql_mode
mysql_query('set @@global.sql_mode = @orig_mode');

เกี่ยวกับมัน.


1
นี่ไม่ได้ตอบคำถามที่ว่าทำไม MySQL ถึงมีพฤติกรรมทั้งหมด แต่ขอบคุณที่แบ่งปันวิธีการของคุณเพื่อให้ผู้อื่นได้รับประโยชน์เช่นกัน ยินดีต้อนรับสู่ Stack Overflow!
GargantuChet

1
ใช่ฉันรู้ว่า ... ฉันจะต้องตรวจสอบโหมด STRICT เพิ่มเติมเพื่อดูว่าเหมาะสมหรือไม่ - เนื่องจาก MySQL ส่งสัญญาณเตือนไปยังกล่องของ Nix แต่ล้มเหลวในกล่อง Windows นั่นเป็นข้อบ่งชี้ว่ามีบางอย่างผิดปกติกับการใช้งานโดยไม่คำนึงถึงแพลตฟอร์ม คุณจะสังเกตเห็นว่าในเอกสารของ MySQL มีประกาศนี้: "คอลัมน์ BLOB และ TEXT ไม่สามารถมีค่าเริ่มต้น" ดังนั้นเหตุผลปรากฏว่าการใช้งานในรุ่นก่อน 5 ถูกใช้งานจริงบนแพลตฟอร์มทั้งหมด
เรือนกระจก Darrell

3

สำหรับ Ubuntu 16.04:

วิธีการปิดการใช้งานโหมดเข้มงวดใน MySQL 5.7:

แก้ไขไฟล์ /etc/mysql/mysql.conf.d/mysqld.cnf

หากบรรทัดด้านล่างมีอยู่ใน mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

จากนั้นแทนที่ด้วย

sql_mode='MYSQL40'

มิฉะนั้น

เพียงเพิ่มบรรทัดด้านล่างใน mysqld.cnf

sql_mode='MYSQL40'

ปัญหานี้ได้รับการแก้ไข

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