Tại sao cột văn bản không có giá trị mặc định trong MySQL?


184

Nếu bạn cố gắng tạo một cột văn bản trên một bảng và cung cấp cho nó một giá trị mặc định trong MySQL, bạn sẽ gặp lỗi (ít nhất là trên Windows). Tôi không thể thấy bất kỳ lý do tại sao một cột văn bản không nên có một giá trị mặc định. Không có lời giải thích nào được đưa ra bởi tài liệu MySQL. Nó có vẻ phi logic với tôi (và hơi khó chịu, vì tôi muốn một giá trị mặc định!). Bất cứ ai cũng biết tại sao điều này không được phép?


1
Chúng tôi có thể xem truy vấn bạn đã sử dụng?
Robert

2
Bạn có chắc chắn muốn có một cột văn bản, không phải là một cột VARCHAR? Các cột văn bản dành cho những thứ có thể dài hơn 255 byte.
Scy

5
Đây nên là một bình luận. Ngoài ra, vâng, ý anh là TEXT- những cột đó không thể có giá trị mặc định. VARCHARcó thể.
Pekka

1
Nếu bạn đang sử dụng phpmyadmin để thiết lập cơ sở dữ liệu của mình, có thể bạn muốn điều tra các công cụ / bàn làm việc của mysql ...;)
dmp

1
Có, tôi không cần nhiều hơn 255 ký tự.
Nga

Câu trả lời:


92

Windows MySQL v5 đưa ra một lỗi nhưng Linux và các phiên bản khác chỉ đưa ra cảnh báo. Cái này cần được sửa chữa. WTF?

Đồng thời xem nỗ lực khắc phục lỗi này là lỗi # 19498 trong Bugtracker của MySQL:

Bryce Nesbitt vào ngày 4 tháng 4 năm 2008 4:36 chiều:
Trên MS Windows, quy tắc "không DEFAULT" là một lỗi, trong khi trên các nền tảng khác, nó thường là một cảnh báo. Mặc dù không phải là một lỗi, nhưng nó có thể bị mắc kẹt bởi điều này nếu bạn viết mã trên nền tảng khoan dung và sau đó chạy nó trên một nền tảng nghiêm ngặt:

Cá nhân, tôi xem đây là một lỗi. Tìm kiếm "cột BLOB / văn bản không thể có giá trị mặc định" trả về khoảng 2.940 kết quả trên Google. Hầu hết trong số chúng là các báo cáo về sự không tương thích khi cố gắng cài đặt các tập lệnh DB hoạt động trên một hệ thống nhưng không phải là các hệ thống khác.

Bây giờ tôi đang gặp vấn đề tương tự trên một ứng dụng web Tôi đang sửa đổi cho một trong những khách hàng của mình, ban đầu được triển khai trên Linux MySQL v5.0.83-log. Tôi đang chạy Windows MySQL v5.1.41. Ngay cả khi cố gắng sử dụng phiên bản mới nhất của phpMyAdmin để trích xuất cơ sở dữ liệu, nó không báo cáo mặc định cho cột văn bản được đề cập. Tuy nhiên, khi tôi thử chạy một phần chèn trên Windows (hoạt động tốt khi triển khai Linux), tôi nhận được một lỗi không có mặc định trên cột ABC. Tôi cố gắng tạo lại bảng cục bộ với mặc định rõ ràng (dựa trên lựa chọn các giá trị duy nhất cho cột đó) và cuối cùng nhận được cột BLOB / TEXT rất hữu ích không thể có giá trị mặc định .

Một lần nữa, không duy trì khả năng tương thích cơ bản trên các nền tảng là không thể chấp nhận và là một lỗi.


Cách tắt chế độ nghiêm ngặt trong MySQL 5 (Windows):

  • Chỉnh sửa /my.ini và tìm dòng

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Thay thế bằng

    sql_mode='MYSQL40'
  • Khởi động lại dịch vụ MySQL (giả sử rằng đó là mysql5)

    net stop mysql5
    net start mysql5
    

Nếu bạn có quyền truy cập root / admin, bạn có thể thực thi

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

3
Nếu bạn có quyền truy cập root và đang sử dụng phpMyAdmin, hãy truy cập trang chính (nhấp vào biểu tượng phpMyAdmin), chuyển đến tab Biến, tìm biến sql_mode và nhấp vào Chỉnh sửa.
Gavin

1
Tôi đang sử dụng CentOS 5.8 và MySQL v 14,14 Phân phối 5.1.71 đưa ra lỗi thay vì cảnh báo khi cố gắng đặt giá trị mặc định thành trường văn bản. Chỉ muốn thông báo rằng nó không hoạt động trên mọi nền tảng Linux.
Alex

OS X ít nhất dường như có lỗi trong những ngày này. Các tài liệu dev.mysql.com/doc/refman/5.7/en/blob.html nói "cột BLOB và văn bản không thể có giá trị DEFAULT." FWIW (nhưng không phải tại sao)
rogerdpack

31

Không có bất kỳ kiến ​​thức sâu sắc nào về công cụ myQuery, tôi sẽ nói điều này nghe giống như một chiến lược tiết kiệm bộ nhớ. Tôi giả sử lý do đằng sau đoạn này từ các tài liệu :

Mỗi giá trị BLOB hoặc văn bản được thể hiện bên trong bởi một đối tượng được phân bổ riêng. Điều này trái ngược với tất cả các loại dữ liệu khác, trong đó lưu trữ được phân bổ một lần cho mỗi cột khi bảng được mở.

Có vẻ như việc điền trước các loại cột này sẽ dẫn đến việc sử dụng bộ nhớ và hình phạt hiệu suất.


5
-1: Lưu trữ dữ liệu, chẳng hạn như tên thành phố, trong cột văn bản thực sự chiếm ít bộ nhớ hơn so với việc lưu trữ cùng một dữ liệu trong cột CHAR hoặc VARCHAR.
David Cary

5
@david chương hướng dẫn tôi trích dẫn không phải là về lưu trữ, mà là truy xuất.
Pekka

1
Tôi không thấy điều đó sẽ dẫn đến bất kỳ hình phạt sử dụng bộ nhớ và hiệu suất bất thường nào. Rõ ràng khi người dùng xác định một giá trị mặc định, anh ta mong đợi một hiệu suất đạt được bất kể loại dữ liệu là gì (đặc biệt là trên các hoạt động hàng loạt). Tuy nhiên, theo như tôi hiểu thì bạn nói rằng đối với trường BLOB / TEXT, hiệu năng này tương đối cao so với các loại dữ liệu khác? Và làm thế nào điều đó có liên quan đến thực tế là BLOB / TEXT được lưu trữ bên trong như một đối tượng tách biệt? Điều này không có ý nghĩa gì với tôi.
kỳ dị

27
IMHO nó không phải là một chiến lược tiết kiệm bộ nhớ. Đó là một lỗi hoặc những người đã viết nó là điên rồ. Và tôi nghĩ đó là cái sau vì họ không thể sửa nó trong ít nhất 8 năm nay. Các chức năng cơ bản mà mọi cơ sở dữ liệu khác có.
kỳ dị

2
Không quan trọng, nó vẫn là một lựa chọn cho những người muốn sử dụng nó.
Nhím

15

Bạn có thể có được hiệu ứng tương tự như một giá trị mặc định bằng cách sử dụng kích hoạt

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

Như câu hỏi chính:

Bất cứ ai cũng biết tại sao điều này không được phép?

vẫn chưa được trả lời, tôi đã thực hiện một tìm kiếm nhanh và tìm thấy một bổ sung tương đối mới từ một nhà phát triển MySQL tại MySQL Bugs :

[17/03/2017 15:11] Ståle Deraas

Đăng bởi nhà phát triển:

Đây thực sự là một yêu cầu tính năng hợp lệ và thoạt nhìn có vẻ không quan trọng để thêm vào. Nhưng giá trị TEXT / BLOBS không được lưu trữ trực tiếp trong bộ đệm bản ghi được sử dụng để đọc / cập nhật bảng. Vì vậy, nó phức tạp hơn một chút để gán giá trị mặc định cho chúng.

Đây không phải là câu trả lời chắc chắn, nhưng ít nhất là một điểm khởi đầu cho câu hỏi tại sao .

Trong lúc này, tôi sẽ chỉ viết mã xung quanh nó và làm cho cột không thể hoặc gán rõ ràng một ''giá trị (mặc định ) cho mỗi inserttừ mã ứng dụng ...


13

"Hỗ trợ DEFAULT trong các cột văn bản / BLOB" là một yêu cầu tính năng trong Trình sửa lỗi MySQL (Lỗi # 21532) .

Tôi thấy tôi không phải là người duy nhất muốn đặt một giá trị mặc định trong cột văn bản. Tôi nghĩ tính năng này nên được hỗ trợ trong phiên bản sau của MySQL.

Điều này không thể được sửa trong phiên bản 5.0 của MySQL, vì rõ ràng nó sẽ gây ra sự không tương thích và dataloss nếu bất cứ ai cố gắng chuyển cơ sở dữ liệu qua lại giữa các cơ sở dữ liệu (hiện tại) không hỗ trợ tính năng đó và bất kỳ cơ sở dữ liệu nào hỗ trợ tính năng đó


Dường như với tôi, bạn sẽ có thể thay đổi nó giữa "" và NULL cho một cột văn bản cho phép null. Nó dường như không thể làm được.
phpguru

6

Tôi thường chạy các trang trên Linux, nhưng tôi cũng phát triển trên máy Windows cục bộ. Tôi đã gặp phải vấn đề này nhiều lần và chỉ sửa các bảng khi gặp sự cố. Tôi đã cài đặt một ứng dụng ngày hôm qua để giúp đỡ ai đó và tất nhiên lại gặp vấn đề. Vì vậy, tôi quyết định đã đến lúc tìm hiểu chuyện gì đang xảy ra - và tìm thấy chủ đề này. Tôi thực sự không thích ý tưởng thay đổi sql_mode của máy chủ sang chế độ trước đó (theo mặc định), vì vậy tôi đã đưa ra một giải pháp đơn giản (tôi nghĩ).

Giải pháp này tất nhiên sẽ yêu cầu các nhà phát triển bọc các kịch bản tạo bảng của họ để bù đắp cho vấn đề MySQL đang chạy trên Windows. Bạn sẽ thấy các khái niệm tương tự trong các tệp kết xuất. Một cảnh báo LỚN là điều này có thể / sẽ gây ra vấn đề nếu phân vùng được sử dụng.

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

Đó là về nó.


1
Điều này không giải quyết được câu hỏi tại sao MySQL có hành vi nào cả, nhưng cảm ơn vì đã chia sẻ cách tiếp cận của bạn để những người khác cũng có thể hưởng lợi. Chào mừng bạn đến với Stack Overflow!
GargantuChet

1
Tôi biết ... Tôi sẽ phải xem xét thêm về chế độ STRICT để xem có hợp lý không - vì MySQL đưa ra cảnh báo trên các hộp của Nix, nhưng không thành công trên các hộp Windows. Đó là một dấu hiệu cho thấy có điều gì đó không ổn với việc triển khai bất kể nền tảng. Bạn sẽ nhận thấy rằng trong tài liệu của MySQL, có thông báo này: "Cột BLOB và văn bản không thể có giá trị DEFAULT." Vì vậy, về mặt logic, có vẻ như việc triển khai trong các phiên bản trước 5 đã thực sự bị phá vỡ trên tất cả các nền tảng.
Nhà kính Darrell

3

Đối với Ubuntu 16.04:

Cách tắt chế độ nghiêm ngặt trong MySQL 5.7:

Chỉnh sửa tập tin /etc/mysql/mysql.conf.d/mysqld.cnf

Nếu dòng dưới đây tồn tại trong mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Sau đó thay thế nó bằng

sql_mode='MYSQL40'

Nếu không thì

Chỉ cần thêm dòng dưới đây trong mysqld.cnf

sql_mode='MYSQL40'

Vấn đề này đã được giải quyết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.