Tôi có thể sử dụng một hàm cho giá trị mặc định trong MySql không?


93

Tôi muốn làm một cái gì đó như thế này:


create table app_users
(
    app_user_id smallint(6) not null auto_increment primary key,
    api_key     char(36) not null default uuid()
);

Tuy nhiên điều này dẫn đến một lỗi, có cách nào để gọi một hàm cho giá trị mặc định trong mysql không?

cảm ơn.

Câu trả lời:


129

Không, bạn không thể.

Tuy nhiên, bạn có thể dễ dàng tạo một trình kích hoạt để thực hiện việc này, chẳng hạn như:

TẠO TRIGGER trước_insert_app_users
  TRƯỚC KHI CHÈN VÀO app_users 
  CHO MỖI HÀNG
  SET new.api_key = uuid ();

2
@Xem stackoverflow.com/questions/6280789/… để điền UUID vào các hàng hiện có.
Sam Barnum

2
Điều này không hoàn toàn giống với việc có giá trị DEFAULT. Làm cách nào để thay đổi câu trả lời này để chỉ đặt khóa nếu giá trị là NULL?
ToolmakerSteve

1
Đáng buồn là MySQL đã tồn tại lâu như vậy nhưng bạn không thể triển khai UUID mặc định cho một cột mà không có trình kích hoạt. Lý do cho điều này là do công nghệ của những năm 1980 dường như vẫn tồn tại trong mã cơ sở MySQL (tìm kiếm "chúng ta không thể có những thứ tốt đẹp"): percona.com/blog/2013/04/08/…
RyanNerd

1
@RodolVelasco chức năng uuid được xây dựng để có khả năng chống va chạm cao. Nhiều hơn so với md5. Ngay sau khi bạn md5 UUID bạn có nguy cơ cao của id va chạm
Cruncher

2
SET new.api_key = COALESCE(new.api_key, uuid())để bảo tồn các giá trị hiện có.
Ryan

29

Kể từ mysql v8.0.13 , có thể sử dụng một biểu thức làm giá trị mặc định cho một trường:

Giá trị mặc định được chỉ định trong mệnh đề DEFAULT có thể là một hằng số theo nghĩa đen hoặc một biểu thức. Với một ngoại lệ, hãy đặt các giá trị mặc định của biểu thức trong dấu ngoặc đơn để phân biệt chúng với các giá trị mặc định của hằng số theo nghĩa đen.

CREATE TABLE t1 (
  uuid_field     VARCHAR(32) DEFAULT (uuid()),
  binary_uuid    BINARY(16)  DEFAULT (UUID_TO_BIN(UUID()))
);

1
Lưu ý rằng theo các tài liệu đã được liên kết trong câu trả lời: ... các chức năng được lưu trữ và các chức năng do người dùng xác định không được phép . Tức là, các hàm duy nhất có thể được sử dụng làm biểu thức mặc định là các hàm tích hợp sẵn.
asherbar

2
Kể từ tháng 5 năm 2020, đây sẽ là câu trả lời chính xác. Các câu trả lời khác sử dụng trình kích hoạt đã lỗi thời.
John Stock

20

Như đã nói, bạn không thể.

Nếu bạn muốn mô phỏng hành vi này, bạn có thể sử dụng trình kích hoạt theo cách này:

CREATE TRIGGER before_insert_app_users
BEFORE INSERT ON app_users
FOR EACH ROW
  IF new.uuid IS NULL
  THEN
    SET new.uuid = uuid();
  END IF;

Bạn vẫn phải cập nhật các hàng hiện có trước đó, như sau:

UPDATE app_users SET uuid = (SELECT uuid());

8

Rất tiếc là không, MySQL 5 yêu cầu các hằng số cho mặc định. Vấn đề đã được thảo luận chi tiết hơn trong liên kết bên dưới. Nhưng câu trả lời duy nhất là cho phép null và thêm trình kích hoạt bảng.

MySQL gần đây chỉ chấp nhận UUID như một phần của gói DB của họ và nó không phong phú về tính năng như chúng tôi mong muốn.

http://www.phpbuilder.com/board/showthread.php?t=10349169


1
Tôi nên nói thêm rằng việc cho phép NULL và dựa vào các trình kích hoạt có thể hoạt động, nhưng hầu hết các nhà phát triển sẽ coi đó là một giải pháp rất hack-y. Cá nhân tôi sẽ không giới thiệu nó nhưng cho mỗi người của họ.
TravisO

6

Tôi tin rằng bạn không thể :

giá trị mặc định phải là một hằng số; nó không thể là một hàm hay một biểu thức


Không đúng, bạn có thể sử dụng getdate ()
amr osama

6
@amrosama - Không, bạn không thể. getdate()thậm chí không phải là một hàm MySQL. Liên kết trong câu trả lời giải thích ngoại lệ duy nhất: «bạn có thể chỉ định CURRENT_TIMESTAMP làm mặc định cho cột TIMESTAMP» .
Álvaro González

1
CURRENT_TIMESTAMP là "chức năng" duy nhất có thể được sử dụng làm giá trị mặc định. Mọi thứ khác phải là một hằng số (thật không may).
Troy Morehouse

3
Về mặt kỹ thuật, tôi muốn nói AUTO_INCREMENT cũng có thể được xem như một "chức năng" để đặt động một giá trị mặc định.
Rikaelus

1

Lưu ý rằng UUID()trả về của MySQL CHAR(36)và lưu trữ UUID dưới dạng văn bản (như được hiển thị trong các câu trả lời khác) rõ ràng là không hiệu quả. Thay vào đó, cột phải là BINARY(16)và bạn có thể sử dụng UUID_TO_BIN()khi chèn dữ liệu và BIN_TO_UUID()khi đọc lại.

CREATE TABLE app_users
(
    app_user_id SMALLINT(6) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    api_key     BINARY(16)
);

CREATE TRIGGER before_insert_app_users
BEFORE INSERT ON app_users
FOR EACH ROW
  IF new.api_key IS NULL
  THEN
    SET new.api_key = UUID_TO_BIN(UUID());
  END IF;

Lưu ý rằng vì MySQL không thực sự biết đây là UUID nên có thể khó khắc phục sự cố với nó được lưu trữ dưới dạng nhị phân. Bài viết này giải thích cách tạo một cột được tạo sẽ chuyển đổi UUID thành văn bản khi cần thiết mà không chiếm bất kỳ dung lượng nào hoặc lo lắng về việc giữ các phiên bản văn bản và nhị phân riêng biệt được đồng bộ hóa: https://mysqlserverteam.com/storing-uuid-values-in -mysql-bảng /


0

Tôi không chắc liệu các câu trả lời trên có dành cho phiên bản cũ hơn hay không, nhưng tôi đã thấy ở đâu đó rằng bạn có thể thực hiện việc này bằng cách sử dụng hàm unax (). Tôi đã thử nó và nó hoạt động. (maria db phiên bản 10.2)

Bạn có thể làm

.... column_name binary(16) not null default unhex(replace(uuid(),'-',''))   

Và nó hoạt động. Để xem uuid chỉ cần thực hiện hex (column_name).


0

Trong MariaDB bắt đầu từ phiên bản 10.2.1, bạn có thể. Xem tài liệu của nó .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
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.