資料類型規格可以有明確或隱含的預設值。
資料類型規格中的 DEFAULT
子句明確指出欄位的預設值。範例value
CREATE TABLE t1 (
i INT DEFAULT -1,
c VARCHAR(10) DEFAULT '',
price DOUBLE(16,2) DEFAULT 0.00
);
SERIAL DEFAULT VALUE
是一種特殊情況。在整數欄位的定義中,它是 NOT NULL AUTO_INCREMENT UNIQUE
的別名。
明確 DEFAULT
子句處理的某些方面與版本相關,如下所述。
DEFAULT
子句中指定的預設值可以是常值常數或運算式。除了一種例外情況外,請將運算式預設值括在括號內,以區別它們與常值常數預設值。範例
CREATE TABLE t1 (
-- literal defaults
i INT DEFAULT 0,
c VARCHAR(10) DEFAULT '',
-- expression defaults
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())
);
例外情況是,對於 TIMESTAMP
和 DATETIME
欄位,您可以將 CURRENT_TIMESTAMP
函數指定為預設值,而無需括在括號中。請參閱 第 13.2.5 節,「TIMESTAMP 和 DATETIME 的自動初始化和更新」。
BLOB
、TEXT
、GEOMETRY
和 JSON
資料類型只能在值寫為運算式時才可被指定為預設值,即使運算式值是常值也是如此。
這是允許的(常值預設值指定為運算式)
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
這會產生錯誤(常值預設值未指定為運算式)
CREATE TABLE t2 (b BLOB DEFAULT 'abc');
運算式預設值必須遵守下列規則。如果運算式包含不允許的結構,就會發生錯誤。
允許使用常值、內建函數(確定性和非確定性)和運算子。
不允許使用子查詢、參數、變數、儲存函數和可載入函數。
運算式預設值不能取決於具有
AUTO_INCREMENT
屬性的欄位。一個欄位的運算式預設值可以參考其他表格欄位,但參考產生的欄位或具有運算式預設值的欄位必須是參考表格定義中較早出現的欄位。也就是說,運算式預設值不能包含對產生欄位或具有運算式預設值的欄位的前向參考。
排序限制也適用於使用
ALTER TABLE
來重新排序表格欄位。如果產生的表格具有包含對產生欄位或具有運算式預設值的欄位的前向參考的運算式預設值,則陳述式會失敗。
如果運算式預設值的任何元件取決於 SQL 模式,除非在所有使用期間 SQL 模式都相同,否則表格的不同使用可能會產生不同的結果。
對於 CREATE TABLE ... LIKE
和 CREATE TABLE ... SELECT
,目的地表格會保留原始表格的運算式預設值。
如果運算式預設值參考非確定性函數,則任何導致運算式被評估的陳述式對於以陳述式為基礎的複寫都是不安全的。這包括諸如 INSERT
和 UPDATE
等陳述式。在此情況下,如果二進位日誌記錄已停用,則陳述式會照常執行。如果二進位日誌記錄已啟用且 binlog_format
設定為 STATEMENT
,則陳述式會被記錄和執行,但會將警告訊息寫入錯誤日誌,因為複本可能會發散。當 binlog_format
設定為 MIXED
或 ROW
時,陳述式會照常執行。
當插入新列時,可以使用省略欄位名稱或將欄位指定為 DEFAULT
來插入具有運算式預設值的欄位的預設值(就像具有常值預設值的欄位一樣)。
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
)
並非所有儲存引擎都允許運算式預設值。對於不允許的引擎,會發生 ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED
錯誤。
如果預設值評估為與宣告的欄位類型不同的資料類型,則會根據通常的 MySQL 類型轉換規則發生隱含強制轉換為宣告的類型。請參閱 第 14.3 節,「運算式評估中的類型轉換」。
如果資料類型規格不包含明確的 DEFAULT
值,則 MySQL 會按如下方式決定預設值:
如果欄位可以將 NULL
作為值,則欄位會定義為具有明確的 DEFAULT NULL
子句。
如果欄位不能接受 NULL
作為值,MySQL 會定義該欄位時不帶有明確的 DEFAULT
子句。
對於輸入到沒有明確 DEFAULT
子句的 NOT NULL
欄位的資料,如果 INSERT
或 REPLACE
陳述式中沒有包含該欄位的值,或是 UPDATE
陳述式將該欄位設為 NULL
,MySQL 會根據當時生效的 SQL 模式來處理該欄位。
如果啟用了嚴格 SQL 模式,則對於交易式資料表會發生錯誤,並且該陳述式會被回滾。對於非交易式資料表,也會發生錯誤,但如果這發生在多列陳述式的第二列或後續列,則會插入先前的列。
如果未啟用嚴格模式,MySQL 會將欄位設為該欄位資料類型的隱含預設值。
假設資料表 t
的定義如下
CREATE TABLE t (i INT NOT NULL);
在這種情況下,i
沒有明確的預設值,因此在嚴格模式下,以下每個陳述式都會產生錯誤且不會插入任何列。當不使用嚴格模式時,只有第三個陳述式會產生錯誤;前兩個陳述式會插入隱含的預設值,但第三個陳述式會失敗,因為 DEFAULT(i)
無法產生值。
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
對於給定的資料表,SHOW CREATE TABLE
陳述式會顯示哪些欄位具有明確的 DEFAULT
子句。
隱含預設值的定義如下
對於數值型別,預設值為
0
,但使用AUTO_INCREMENT
屬性宣告的整數或浮點數型別除外,其預設值為序列中的下一個值。對於
TIMESTAMP
以外的日期和時間型別,預設值為該型別適當的「零」值。如果啟用了explicit_defaults_for_timestamp
系統變數,TIMESTAMP
也是如此(請參閱第 7.1.8 節,「伺服器系統變數」)。否則,對於資料表中的第一個TIMESTAMP
欄位,預設值為目前的日期和時間。請參閱 第 13.2 節,「日期和時間資料型別」。