mysql+默认值+default_十六、MySQL 中数据类型的默认值 - default 约束-搜云库
MySQL 中,所有的數(shù)據(jù)類型,都可以顯式或隱式的擁有默認(rèn)值。
我們可以使用 DEFAULT 約束顯式的為列指定一個(gè)默認(rèn)值。比如
CREATE TABLE t1 (
i INT DEFAULT -1,
c VARCHAR(10) DEFAULT '',
price DOUBLE(16,2) DEFAULT 0.00
);
在上面這條語句中,我們?yōu)?int 類型的 i 列指定了默認(rèn)值 -1 ,為 varchar 類型的 c 列指定了默認(rèn)值 '' ,為 double 類型的 price 列指定了默認(rèn)值 0.00。也就是說,當(dāng)我們插入數(shù)據(jù)的時(shí)候,并不需要完整的為每一列指定值。如果沒有指定值,那么 MySQL 就會(huì)使用默認(rèn)值填充。
但是,DEFAULT 約束有有一個(gè)特例,就是 SERIAL DEFAULT VALUE。等于類型為整形的列,它的作用相當(dāng)于 NOT NULL AUTO_INCREMENT UNIQUE。
其實(shí)這不怪 DEFAULT ,是 SERIAL 的鍋。
但是,default 并不是沒有 bug,顯式 DEFAULT 約束處理的某些方面依賴于版本。
MySQL 8.0.13 中處理顯式默認(rèn)值
DEFAULT 約束中指定的默認(rèn)值可以是文字常量或表達(dá)式。
如果使用表達(dá)式作為默認(rèn)值,則需要表達(dá)式默認(rèn)值括在括號(hào)內(nèi) () ,以將它們與文字常量默認(rèn)值區(qū)分開來。
例如
CREATE TABLE t1 (
-- 常量默認(rèn)值
i INT DEFAULT 0,
c VARCHAR(10) DEFAULT '',
-- 表達(dá)式默認(rèn)值
f FLOAT DEFAULT (RAND() * RAND()),
b BINARY(16) DEFAULT (UUID_TO_BIN(UUID())),
d DATE DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR),
p POINT DEFAULT (Point(0,0)),
j JSON DEFAULT (JSON_ARRAY())
);
但是,這有一個(gè)例外。這個(gè)例外就是: TIMESTAMP 和 DATETIME 列。
對(duì)于 TIMESTAMP 和 DATETIME 列,我們可以將 CURRENT_TIMESTAMP 函數(shù)指定為默認(rèn)值,而需要添加括號(hào)。
CREATE TABLE t1 (
-- 常量默認(rèn)值
c TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
u DATETIME DEFAULT CURRENT_TIMESTAMP,
);
而對(duì)于 BLOB,TEXT,GEOMETRY和 JSON 數(shù)據(jù)類型,只有在將值寫為表達(dá)式時(shí),才能分配默認(rèn)值,即使表達(dá)式值是文字也是如此。
例如,下面這種寫法是允許的,也就是使用文字字面量表達(dá)式
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
但下面這種寫法則是不允許的,因?yàn)樗且粋€(gè)字面量而不是一個(gè)表達(dá)式
CREATE TABLE t2 (b BLOB DEFAULT 'abc');
表達(dá)式默認(rèn)值必須遵守以下規(guī)則。如果表達(dá)式包含不允許的構(gòu)造,則會(huì)發(fā)生錯(cuò)誤
允許使用文字,內(nèi)置函數(shù)(確定性和非確定性)和運(yùn)算符
不允許使用子查詢,參數(shù),變量,存儲(chǔ)函數(shù)和用戶定義的函數(shù)
表達(dá)式默認(rèn)值不能依賴于具有 AUTO_INCREMENT 屬性的列。
某一列的表達(dá)式默認(rèn)值可以引用另外一張表中的列,但是對(duì)生成的列或具有表達(dá)式默認(rèn)值的列的引用必須是對(duì)于在表定義中較早出現(xiàn)的列。也就是說,表達(dá)式默認(rèn)值不能包含對(duì)生成的列或具有表達(dá)式默認(rèn)值的列的前向引用。翻譯成白話文就是,引用的列必須已經(jīng)存在。
排序 ( ordering ) 約束也適用于使用 ALTER TABLE 重新排序表列。如果結(jié)果表的表達(dá)式默認(rèn)值包含對(duì)具有表達(dá)式默認(rèn)值的生成列或列的前向引用,則該語句將失敗
注意: 如果表達(dá)式默認(rèn)值的任何組件取決于 SQL 模式,則表的不同用法可能會(huì)出現(xiàn)不同的結(jié)果,除非在所有使用過程中 SQL 模式都相同
對(duì)于語句 CREATE TABLE ... LIKE 和 CREATE TABLE ... SELECT ,目標(biāo)表保留原始表中的表達(dá)式默認(rèn)值。
如果表達(dá)式默認(rèn)值引用非確定性函數(shù),則導(dǎo)致表達(dá)式計(jì)算的任何語句對(duì)于基于語句的復(fù)制都是不安全的。包括 INSERT,UPDATE 和 ALTER TABLE 等語句
插入新行時(shí),可以通過省略列名或?qū)⒘兄付?DEFAULT 來插入具有表達(dá)式 default 的列的默認(rèn)值(就像具有文字默認(rèn)值的列一樣)
mysql> CREATE TABLE t4 (uid BINARY(16) DEFAULT (UUID_TO_BIN(UUID())));
mysql> INSERT INTO t4 () VALUES();
mysql> INSERT INTO t4 () VALUES(DEFAULT);
mysql> SELECT BIN_TO_UUID(uid) AS uid FROM t4;
+--------------------------------------+
| uid |
+--------------------------------------+
| f1109174-94c9-11e8-971d-3bf1095aa633 |
| f110cf9a-94c9-11e8-971d-3bf1095aa633 |
+--------------------------------------+
需要注意的是,使用 DEFAULT(col_name) 指定命名列的默認(rèn)值的語法僅允許出現(xiàn)在具有文字默認(rèn)值的列,而不允許出現(xiàn)在具有表達(dá)式默認(rèn)值的列。
另一個(gè)需要注意的是,并非所有存儲(chǔ)引擎都允許表達(dá)式默認(rèn)值。對(duì)于那些沒有的,會(huì)引發(fā) ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED 錯(cuò)誤。
如果默認(rèn)值的計(jì)算結(jié)果與聲明的列類型不同,則根據(jù)通用的 MySQL 類型轉(zhuǎn)換規(guī)則對(duì)聲明的類型進(jìn)行隱式強(qiáng)制。
MySQL 8.0.13 之前的版本中處理顯式默認(rèn)值
MySQL 8.0.13 之前的版本,DEFAULT 約束中指定的默認(rèn)值必須是文字常量,而不能是一個(gè)函數(shù)或表達(dá)式。
但有一個(gè)例外,這個(gè)例外就是: TIMESTAMP 和 DATETIME 列。
這意味著,我們不能將 date 列的默認(rèn)值設(shè)置為函數(shù)的值,例如 NOW() 或 CURRENT_DATE 。
而對(duì)于 BLOB , TEXT ,GEOMETRY 和 JSON 數(shù)據(jù)類型,根本就不允許分配默認(rèn)值。
同樣的,如果默認(rèn)值的計(jì)算結(jié)果與聲明的列類型不同,則根據(jù)通用的 MySQL 類型轉(zhuǎn)換規(guī)則對(duì)聲明的類型進(jìn)行隱式強(qiáng)制。
處理隱式默認(rèn)值
如果在定義表結(jié)構(gòu)時(shí)不使用 DEFAULT 約束為列顯式定義默認(rèn)值,MySQL 將自己決定如何設(shè)置默認(rèn)值。
如果列可以將 NULL 作為值,則會(huì)使用顯式的 DEFAULT NULL 子句定義該列。其實(shí)不用顯式,因?yàn)樗褪悄J(rèn)的定義。
如果列不能將 NULL 作為值,則 MySQL 會(huì)定義沒有顯式 DEFAULT 子句的列。也就是并不會(huì)添加 DEFAULT 約束。
但這兩條規(guī)則有一個(gè)例外,如果列被定義為 PRIMARY KEY 的一部分但未顯式設(shè)置為 NOT NULL,則 MySQL 將其創(chuàng)建為 NOT NULL 列( 因?yàn)镻RIMARY KEY 列必須為 NOT NULL )。
對(duì)于沒有顯式 DEFAULT 約束的 NOT NULL 列的數(shù)據(jù)輸入,如果 INSERT 或 REPLACE 語句不包含該列的值,或者 UPDATE 語句將列設(shè)置為 NULL ,MySQL 會(huì)根據(jù)當(dāng)時(shí)生效的 SQL 模式處理列:
如果啟用了嚴(yán)格的 SQL 模式,則事務(wù)表會(huì)發(fā)生錯(cuò)誤,并且會(huì)回滾 SQL 語句。對(duì)于非事務(wù)性表,會(huì)發(fā)生錯(cuò)誤,但如果多行語句的第二行或后續(xù)行發(fā)生這種情況,則前面的行會(huì)正常插入。
如果未啟用嚴(yán)格模式,MySQL 會(huì)將列設(shè)置為列數(shù)據(jù)類型的隱式默認(rèn)值
對(duì)于這段敘述,總覺得很拗口,好不,我們舉個(gè)例子來說明下,假設(shè)表 t 定義如下
CREATE TABLE t (i INT NOT NULL);
上面這個(gè)表定義語句中,我們并沒有為 i 字段顯式的定義默認(rèn)值,因此在嚴(yán)格模式下,以下每個(gè)語句都會(huì)產(chǎn)生錯(cuò)誤,并且不會(huì)插入任何行。
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
不使用嚴(yán)格模式時(shí),只有第三個(gè)語句產(chǎn)生錯(cuò)誤,因?yàn)榍皟蓚€(gè)語句插入了隱式默認(rèn)值,但第三個(gè)語句失敗,因?yàn)?DEFAULT(i) 無法生成值。
對(duì)于給定的表,我們可以使用 SHOW CREATE TABLE 語句顯示哪些列具有顯式 DEFAULT 約束。
而對(duì)于隱式默認(rèn)值,則定義如下
對(duì)于數(shù)字類型,默認(rèn)值為 0,但對(duì)于使用 AUTO_INCREMENT 屬性聲明的整數(shù)或浮點(diǎn)類型,默認(rèn)值是序列中的下一個(gè)值。
對(duì)于 TIMESTAMP 以外的日期和時(shí)間類型,默認(rèn)值為該類型的相應(yīng) 「 零 」 值。如果啟用了 explicit_defaults_for_timestamp 系統(tǒng)變量,那么 TIMESTAMP 類型的列的默認(rèn)值也是 「 零 」 值。否則,對(duì)于表中的第一個(gè) TIMESTAMP 列,默認(rèn)值為當(dāng)前日期和時(shí)間。
對(duì)于 ENUM 以外的字符串類型,默認(rèn)值為空字符串 ( "")。對(duì)于 ENUM 類型,默認(rèn)值是第一個(gè)枚舉值
干貨推薦
附錄:MySQL 拾遺:系列文章
總結(jié)
以上是生活随笔為你收集整理的mysql+默认值+default_十六、MySQL 中数据类型的默认值 - default 约束-搜云库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos流量测试(ddos流量攻击检测)
- 下一篇: phpmyadmin忘记mysql密码_