Mengapa kolom teks tidak dapat memiliki nilai default di MySQL?

185

Jika Anda mencoba membuat kolom TEXT di atas meja, dan memberinya nilai default di MySQL, Anda mendapatkan kesalahan (setidaknya untuk Windows). Saya tidak dapat melihat alasan mengapa kolom teks tidak memiliki nilai default. Tidak ada penjelasan yang diberikan oleh dokumentasi MySQL. Tampaknya tidak masuk akal bagi saya (dan agak membuat frustrasi, karena saya ingin nilai default!). Adakah yang tahu mengapa ini tidak diizinkan?

Russ
sumber
1
Bisakah kita melihat permintaan yang Anda gunakan?
Robert
2
Anda yakin ingin kolom TEKS, bukan kolom VARCHAR? Kolom TEKS adalah untuk hal-hal yang dapat menjadi lebih dari 255 byte.
scy
5
Ini harus menjadi komentar. Juga, ya, maksudnya TEXT- kolom-kolom itu tidak dapat memiliki nilai default. VARCHARbisa.
Pekka
1
Jika Anda menggunakan phpmyadmin untuk mengatur database Anda, mungkin ingin menyelidiki alat mysql gui / workbench ...;)
dmp
1
Ya, saya membutuhkan lebih dari 255 karakter.
Russ

Jawaban:

92

Windows MySQL v5 membuat kesalahan tetapi Linux dan versi lain hanya memunculkan peringatan. Ini perlu diperbaiki. WTF?

Lihat juga upaya untuk memperbaikinya sebagai bug # 19498 di Bugtracker MySQL:

Bryce Nesbitt pada 4 April 2008 4:36 pm:
Pada MS Windows aturan "no DEFAULT" adalah kesalahan, sedangkan pada platform lain sering kali peringatan. Meskipun bukan bug, Anda mungkin terjebak oleh hal ini jika Anda menulis kode pada platform yang lunak, dan kemudian menjalankannya pada platform yang ketat:

Secara pribadi, saya melihat ini sebagai bug. Mencari "BLOB / TEXT kolom tidak dapat memiliki nilai default" mengembalikan sekitar 2.940 hasil di Google. Kebanyakan dari mereka adalah laporan yang tidak kompatibel ketika mencoba menginstal skrip DB yang bekerja pada satu sistem tetapi tidak pada yang lain.

Saya mengalami masalah yang sama sekarang di webapp saya memodifikasi untuk salah satu klien saya, awalnya digunakan di Linux MySQL v5.0.83-log. Saya menjalankan Windows MySQL v5.1.41. Bahkan mencoba menggunakan versi terbaru dari phpMyAdmin untuk mengekstrak database, itu tidak melaporkan default untuk kolom teks yang dimaksud. Namun, ketika saya mencoba menjalankan insert pada Windows (yang berfungsi dengan baik pada penyebaran Linux) saya menerima kesalahan yang tidak ada default pada kolom ABC. Saya mencoba membuat ulang tabel secara lokal dengan default yang jelas (berdasarkan pada pemilihan nilai unik untuk kolom itu) dan akhirnya menerima kolom BLOB / TEXT yang sangat berguna tidak dapat memiliki nilai default .

Sekali lagi, tidak mempertahankan kompatibilitas dasar lintas platform tidak dapat diterima dan merupakan bug.


Cara menonaktifkan mode ketat di MySQL 5 (Windows):

  • Edit /my.ini dan cari baris

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Ganti dengan

    sql_mode='MYSQL40'
  • Mulai ulang layanan MySQL (dengan asumsi itu adalah mysql5)

    net stop mysql5
    net start mysql5

Jika Anda memiliki akses root / admin, Anda mungkin dapat menjalankannya

mysql_query("SET @@global.sql_mode='MYSQL40'");
Ku Logix
sumber
3
Jika Anda memiliki akses root dan menggunakan phpMyAdmin, buka halaman utama (klik logo phpMyAdmin), buka tab Variables, cari variabel sql_mode, dan klik Edit.
Gavin
1
Saya menggunakan CentOS 5.8 dan MySQL v 14.14 Distrib 5.1.71 melempar kesalahan alih-alih peringatan saat mencoba menetapkan nilai default ke bidang TEXT. Hanya ingin melihat itu tidak berfungsi pada setiap platform Linux.
Alex
OS X paling tidak sepertinya melakukan kesalahan saat ini. Docs dev.mysql.com/doc/refman/5.7/en/blob.html mengatakan "BLOB dan TEXT kolom tidak dapat memiliki nilai DEFAULT." FWIW (tapi bukan mengapa)
rogerdpack
31

Tanpa pengetahuan mendalam tentang mesin mySQL, saya akan mengatakan ini terdengar seperti strategi penghematan memori. Saya menganggap alasannya ada di belakang paragraf ini dari dokumen :

Setiap nilai BLOB atau TEXT diwakili secara internal oleh objek yang dialokasikan secara terpisah. Ini berbeda dengan semua tipe data lainnya, yang penyimpanannya dialokasikan satu kali per kolom ketika tabel dibuka.

Sepertinya pra-mengisi jenis kolom ini akan menyebabkan penggunaan memori dan hukuman performa.

Pekka
sumber
5
-1: Menyimpan data, seperti nama kota, dalam kolom TEXT sebenarnya membutuhkan lebih sedikit memori total daripada menyimpan data yang sama dalam kolom CHAR atau VARCHAR.
David Cary
5
@david bab manual saya kutip bukan tentang penyimpanan, tetapi pengambilan.
Pekka
1
Saya tidak melihat bagaimana hal itu akan menyebabkan penggunaan memori yang abnormal dan hukuman kinerja. Jelas ketika seorang pengguna menentukan nilai default, ia mengharapkan performa yang baik tidak peduli apa pun tipe datanya (terutama pada operasi massal). Namun sejauh yang saya mengerti Anda menyatakan bahwa untuk bidang BLOB / TEXT kinerja ini hit relatif tinggi dibandingkan dengan tipe data lainnya? Dan bagaimana hal itu terkait dengan fakta bahwa BLOB / TEXT disimpan secara internal sebagai objek yang terpisah? Ini tidak masuk akal bagi saya.
Aneh
27
IMHO itu bukan strategi penghematan memori. Entah itu bug atau orang yang menulisnya gila. Dan saya pikir itu yang terakhir karena mereka tidak bisa memperbaikinya selama setidaknya 8 tahun sekarang. Fungsi dasar yang dimiliki setiap database lainnya.
Aneh
2
Tidak masalah, itu tetap harus menjadi pilihan bagi orang yang ingin menggunakannya.
Jurchiks
15

Anda bisa mendapatkan efek yang sama dengan nilai default dengan menggunakan pemicu

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 ;
Tim Child
sumber
14

Sebagai pertanyaan utama:

Adakah yang tahu mengapa ini tidak diizinkan?

masih belum dijawab, saya melakukan pencarian cepat dan menemukan tambahan yang relatif baru dari pengembang MySQL di MySQL Bugs :

[17 Mar 2017 15:11] Ståle Deraas

Diposting oleh pengembang:

Ini memang permintaan fitur yang valid, dan sekilas tampaknya sepele untuk ditambahkan. Tetapi nilai TEXT / BLOBS tidak disimpan secara langsung di buffer catatan yang digunakan untuk membaca / memperbarui tabel. Jadi sedikit lebih rumit untuk menetapkan nilai default untuk mereka.

Ini bukan jawaban yang pasti, tetapi setidaknya titik awal untuk pertanyaan mengapa .

Sementara itu, saya hanya akan kode di sekitarnya dan membuat kolom nullable atau secara eksplisit menetapkan nilai (default '') untuk masing-masing insertdari kode aplikasi ...

Marten Koetsier
sumber
13

"Dukungan untuk DEFAULT dalam kolom TEKS / BLOB" adalah permintaan fitur di Bugtracker MySQL (Bug # 21532) .

Saya tahu saya bukan satu-satunya yang ingin memasukkan nilai default di kolom TEXT. Saya pikir fitur ini harus didukung di versi MySQL yang lebih baru.

Ini tidak dapat diperbaiki di versi 5.0 dari MySQL, karena tampaknya itu akan menyebabkan ketidakcocokan dan dataloss jika ada yang mencoba untuk mentransfer database bolak-balik antara (saat ini) database yang tidak mendukung fitur itu dan setiap database yang mendukung fitur itu.

David Cary
sumber
Menurut saya Anda harus dapat mengubahnya antara "" dan NULL untuk kolom TEXT yang memungkinkan null. Sepertinya tidak mungkin dilakukan.
phpguru
6

Saya biasanya menjalankan situs di Linux, tetapi saya juga mengembangkan pada mesin Windows lokal. Saya sering mengalami masalah ini dan baru saja memperbaiki tabel ketika saya menemui masalah. Saya menginstal aplikasi kemarin untuk membantu seseorang dan tentu saja mengalami masalah lagi. Jadi, saya memutuskan sudah waktunya untuk mencari tahu apa yang sedang terjadi - dan menemukan utas ini. Saya benar-benar tidak menyukai gagasan mengubah sql_mode server ke mode sebelumnya (secara default), jadi saya datang dengan solusi (menurut saya) yang sederhana.

Solusi ini tentu saja mengharuskan pengembang untuk membungkus skrip pembuatan tabel mereka untuk mengkompensasi masalah MySQL yang berjalan pada Windows. Anda akan melihat konsep serupa di file dump. Satu peringatan BESAR adalah bahwa ini dapat / akan menyebabkan masalah jika partisi digunakan.

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

Itu saja.

Darrell Greenhouse
sumber
1
Ini tidak menjawab pertanyaan mengapa MySQL memiliki perilaku sama sekali, tetapi terima kasih telah berbagi pendekatan Anda sehingga orang lain juga mendapat manfaat. Selamat Datang di Stack Overflow!
GargantuChet
1
Ya saya tahu ... Saya harus melihat ke dalam mode STRICT lebih jauh untuk melihat apakah itu masuk akal - karena MySQL melempar peringatan pada kotak Nix, tetapi gagal pada kotak Windows. Itu indikasi bahwa ada sesuatu yang salah dengan implementasi terlepas dari platform. Anda akan melihat bahwa dalam dokumentasi MySQL, ada pemberitahuan ini: "Kolom BLOB dan TEXT tidak dapat memiliki nilai DEFAULT." Jadi secara logis, tampaknya implementasi dalam versi sebelum 5 sebenarnya rusak pada semua platform.
Darrell Greenhouse
3

Untuk Ubuntu 16.04:

Cara menonaktifkan mode ketat di MySQL 5.7:

Edit file /etc/mysql/mysql.conf.d/mysqld.cnf

Jika baris di bawah ini ada di mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Lalu Ganti dengan

sql_mode='MYSQL40'

Jika tidak

Cukup tambahkan baris di bawah ini di mysqld.cnf

sql_mode='MYSQL40'

Ini menyelesaikan masalah.

Shiv Buyya
sumber