MySql'de varsayılan bir değer için bir işlev kullanabilir miyim?


95

Bunun gibi bir şey yapmak istiyorum:


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

Ancak bu bir hatayla sonuçlanır, mysql'de varsayılan bir değer için bir işlevi çağırmanın bir yolu var mı?

Teşekkürler.

Yanıtlar:


130

Hayır, yapamazsınız.

Ancak, bunu yapmak için kolayca bir tetikleyici oluşturabilirsiniz, örneğin:

_İnsert_app_users'dan önce TETİK OLUŞTURUN
  App_users'I EKLEMEDEN ÖNCE 
  HER SIRA İÇİN
  SET new.api_key = uuid ();

2
@ Mevcut satırlarda UUID'leri doldurmak için stackoverflow.com/questions/6280789/… konusuna bakın .
Sam Barnum

2
Bu, VARSAYILAN bir değere sahip olmakla tamamen aynı değildir. Bu yanıtı, yalnızca değer NULL ise anahtarı ayarlamak için nasıl değiştirebiliriz?
ToolmakerSteve

1
MySQL'in uzun süredir var olması üzücü, ancak tetikleyici olmayan bir sütun için varsayılan bir UUID uygulayamazsınız. Bunun nedeni, görünüşe göre hala MySQL temel kodunda var olan 1980 teknolojisinde yerleşiktir ("güzel şeylere sahip olamayız" için arama yapın): percona.com/blog/2013/04/08/…
RyanNerd

1
@RodolVelasco uuid işlevi çarpışmaya son derece dayanıklı olacak şekilde tasarlanmıştır. MD5'ten çok daha fazlası. Uuid'i md5'e bağladığınızda daha yüksek bir kimlik çarpışması riskiniz var
Cruncher

2
SET new.api_key = COALESCE(new.api_key, uuid())mevcut değerleri korumak için.
Ryan

33

İtibariyle MySQL v8.0.13 bir alan için varsayılan değer olarak bir ifade kullanmak mümkündür:

Bir DEFAULT yan tümcesinde belirtilen varsayılan değer, değişmez bir sabit veya bir ifade olabilir. Bir istisna dışında, ifade varsayılan değerlerini, değişmez sabit varsayılan değerlerden ayırmak için parantez içine alın.

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

2
Yanıttaki halihazırda bağlantılı dokümanlar uyarınca: ... saklanan işlevlere ve kullanıcı tanımlı işlevlere izin verilmediğini unutmayın . Yani, varsayılan ifadeler olarak kullanılabilen işlevler yerleşik işlevlerdir.
asherbar

2
Mayıs 2020 itibariyle bu doğru cevap olmalıdır. Tetikleyicileri kullanan diğer yanıtlar geçersizdir.
John Stok

küçük bir ayrıntı: varchar(32)olmalıdırvarchar(36)
Jared Beck

@JaredBeck Eğer çizgileri saklamıyorsanız 32 iyi.
Alvin Thompson

@JohnStock Bu yöntem, kullanıcı tanımlı veya depolanan işlevlerin kullanımına izin vermez, bu nedenle tetikleyicilerin kullanımının eski olduğunu bildirmek biraz erken olabilir.
Alvin Thompson

21

Daha önce de belirtildiği gibi yapamazsınız.

Bu davranışı simüle etmek istiyorsanız, şu şekilde bir tetikleyici kullanabilirsiniz:

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;

Halen önceden var olan satırları şu şekilde güncellemeniz gerekir:

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

9

Maalesef hayır, MySQL 5 varsayılan için sabitler gerektirir. Konu, aşağıdaki bağlantıda çok daha detaylı tartışılmıştır. Ancak tek cevap, null değerine izin vermek ve bir tablo tetikleyicisi eklemektir.

MySQL, kısa süre önce UUID'yi DB paketlerinin bir parçası olarak kabul etti ve bizim istediğimiz kadar zengin özelliklere sahip değil.

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


1
NULL'a izin vermenin ve tetikleyicilere güvenmenin işe yarayabileceğini eklemeliyim, ancak çoğu geliştirici bunu çok hack-y bir çözüm olarak görür. Şahsen tavsiye etmem ama her birine kendi başına.
TravisO

7

İnanıyorum yapamazsınız :

varsayılan değer sabit olmalıdır; bir işlev veya ifade olamaz


Doğru değil, getdate () kullanabilirsiniz
amr osama

6
@amrosama - Hayır, yapamazsınız. getdate()bir MySQL işlevi bile değildir. Yanıttaki bağlantı tek istisnayı açıklıyor: «TIMESTAMP sütunu için varsayılan olarak CURRENT_TIMESTAMP'ı belirtebilirsiniz» .
Álvaro González

1
CURRENT_TIMESTAMP, varsayılan değer olarak kullanılabilen tek "işlevdir". Geri kalan her şey sabit olmalıdır (maalesef).
Troy Morehouse

3
Teknik olarak AUTO_INCREMENT'in dinamik olarak varsayılan bir değer ayarlamak için bir "işlev" olarak da görülebileceğini söyleyebilirim.
Rikaelus

1

MySQL'in UUID()geri dönüşlerinin CHAR(36)ve UUID'leri metin olarak saklamanın (diğer cevaplarda gösterildiği gibi) açıkça verimsiz olduğunu unutmayın. Bunun yerine sütun olmalıdır BINARY(16)ve UUID_TO_BIN()verileri eklerken ve BIN_TO_UUID()geri okurken kullanabilirsiniz .

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;

MySQL bunun bir UUID olduğunu gerçekten bilmediğinden, ikili olarak depolanan problemleri gidermenin zor olabileceğini unutmayın. Bu makale, UUID'yi gerektiği gibi metne dönüştürecek, herhangi bir yer kaplamadan veya ayrı ikili ve metin sürümlerini eşzamanlı tutma endişesi olmadan nasıl oluşturulacağını açıklar: https://mysqlserverteam.com/storing-uuid-values-in -mysql-tablolar /


0

Yukarıdaki yanıtların daha eski bir sürüm için olup olmadığından emin değilim, ancak bunu unhex () işlevini kullanarak yapabileceğiniz bir yer gördüm. Denedim ve işe yarıyor. (maria db sürüm 10.2)

Yapabilirsin

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

ve çalışıyor. Uuid'i görmek için hex (sütun_adı) yapın.


0

MariaDB'de 10.2.1 sürümünden başlayarak yapabilirsiniz. Belgelerine bakın .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.