Cách buộc MySQL nhận 0 làm giá trị tăng tự động hợp lệ


77

Tóm lại, tôi có một tệp SQL mà tôi muốn nhập dưới dạng skeltệp kiểu, vì vậy việc này sẽ được thực hiện lặp đi lặp lại theo chương trình. Tôi có thể chỉnh sửa tệp SQL theo bất kỳ cách nào tôi muốn, nhưng tôi không muốn chạm vào chính ứng dụng đó.

Ứng dụng này sử dụng userid = 0để đại diện cho người dùng ẩn danh. Nó cũng có một mục nhập (trống) có liên quan trong cơ sở dữ liệu để đại diện cho 'người dùng' này. Do đó, dòng trong của tôi skel.sqltrông giống như sau:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (0, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

Vấn đề với điều này là uidmột auto_incrementtrường, về mặt kỹ thuật, 0là một giá trị không hợp lệ. Hoặc ít nhất, nếu bạn đặt nó thành 0, về cơ bản bạn đang nói với MySQL, "Vui lòng chèn id tiếp theo vào trường này."

Bây giờ, tôi cho rằng tôi có thể đặt một truy vấn INSERTsau đó UPDATEvào tệp SQL của mình, nhưng có cách nào để nói với MySQL nói chung rằng có, tôi thực sự muốn chèn 0vào trường này không?

Câu trả lời:


94

Từ câu trả lời tôi nhận được ở đây :

Bạn có thể dùng:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

Như được mô tả ở đây , sẽ ngăn MySQL diễn giải một ID INSERT / UPDATE của 0 là ID trình tự tiếp theo. Hành vi như vậy sẽ được giới hạn ở NULL.

Đó là những gì tôi cho là hành vi khá xấu từ ứng dụng. Bạn sẽ phải thực sự cẩn thận rằng nó được sử dụng nhất quán, đặc biệt nếu bạn chọn triển khai nhân rộng vào một ngày sau đó.


17
Một điều bạn phải cẩn thận: sql_modelà danh sách cờ được phân tách bằng dấu phẩy. Nếu bạn làm vậy sql_mode='NO_AUTO_VALUE_ON_ZERO', bạn có thể vô tình vô hiệu hóa các cờ khác
Kip

Giải pháp này về cơ bản đã hoạt động đối với tôi, tuy nhiên kết xuất của tôi cũng bao gồm một số vị trí trong đó nó đang ghi đè sql_modeở giữa tệp sql và sau đó đặt lại thành biến OLD_SQL_MODEđược đặt để hoàn nguyên về cuối tập lệnh. Điều này đã đè lên tôi NO_AUTO_VALUE_ON_ZEROở giữa kịch bản của tôi khiến nó không hoạt động. Giải pháp của tôi là tạo ra một biến mới của INIT_OLD_SQL_MODEtôi đã sử dụng để thiết lập lại để ở cuối và sau khi tôi đặt sql_modeđể NO_AUTO_VALUE_ON_ZERO, tôi đặt một biến mới OLD_SQL_MODErằng những ghi đè tạm thời có thể thiết lập lại để
Joshua Fricke

27

Kiểm tra chế độ DB sql của bạn với:

SELECT @@[GLOBAL|SESSION].sql_mode;

Nếu nó trống hoặc chưa được đặt, hãy sử dụng:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

HÃY CẨN THẬN! Nếu bạn sử dụng GLOBAL, đây không phải là thay đổi ngay lập tức, bạn cần khởi động lại kết nối của mình để áp dụng cài đặt.

Vì vậy, nếu bạn đang khôi phục dữ liệu từ DB này sang DB khác, và bạn không chắc liệu cài đặt này có được áp dụng hay không, hãy sử dụng SESSIONđể thay đổi ngay lập tức (nó đặt lại khi đóng kết nối). Khi hoàn tất, hãy chèn giá trị 0 và nó sẽ không thay đổi ngay cả khi sql_modeđã thay đổi.

Để đặt lại chế độ này (và các chế độ khác), hãy sử dụng

SET [GLOBAL|SESSION] sql_mode=''

Các giá trị tự động tăng 0 không được khuyến nghị vì chúng không được đặt làm mặc định trong cơ sở dữ liệu MySQL.

Để biết thêm thông tin, hãy kiểm tra chủ đề trang nhà phát triển mysql về điều này

Cập nhật

Đối với MariaDB, sử dụng lệnh được chỉ ra trong nhận xét này

SET sql_mode='NO_AUTO_VALUE_ON_ZERO'

Điều này không hoạt động trên MariaDB, tôi phải sử dụng cái này:SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
hiddeneyes02

@ hiddeneyes02 Đây là một bài đăng từ năm 2010, cảm ơn vì đã nhận xét, tôi sẽ cập nhật câu trả lời :)
IG Pascual

Không hoạt động: SELECT @@ [GLOBAL | SESSION] .sql_mode; Đã hoạt động: SELECT @@ SESSION.sql_mode; Đã hoạt động: SELECT @@ GLOBAL.sql_mode;
azoundria

14

Nếu bạn không muốn xử lý các biến mysql, đây là một thủ thuật hữu ích:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (-1, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

Và sau đó

UPDATE `{{TABLE_PREFIX}}users` SET id = 0 where id = -1;

Rõ ràng, điều này giả định rằng bạn đang sử dụng số nguyên có dấu và không sử dụng giá trị âm cho id bảng của mình.


6
Rõ ràng, nó không hoạt động nếu bạn đang sử dụng một số nguyên không dấu.
fnkr

7

Cách an toàn không thành công:

SET @@session.sql_mode = 
    CASE WHEN @@session.sql_mode NOT LIKE '%NO_AUTO_VALUE_ON_ZERO%' 
        THEN CASE WHEN LENGTH(@@session.sql_mode)>0
            THEN CONCAT_WS(',',@@session.sql_mode,'NO_AUTO_VALUE_ON_ZERO')  -- added, wasn't empty
            ELSE 'NO_AUTO_VALUE_ON_ZERO'                                    -- replaced, was empty
        END
        ELSE @@session.sql_mode                                             -- unchanged, already had NO_AUTO_VALUE_ON_ZERO set
    END
  • Kiểm tra xem NO_AUTO_VALUE_ON_ZERO đã được đặt trong sql_mode chưa
  • Thêm vào sql_mode nếu không trống
  • Chỉ đặt phiên, tôi khuyên bạn chỉ nên sử dụng nó trên những phiên mà bạn cần chèn số 0
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.