MySQL拾遗之数据类型的默认值-default

2023-11-18


MySQL 中,所有的数据类型,都可以显式或隐式的拥有默认值。

我们可以使用 DEFAULT 约束显式的为列指定一个默认值。比如

CREATE TABLE t1 (
  i     INT DEFAULT -1,
  c     VARCHAR(10) DEFAULT '',
  price DOUBLE(16,2) DEFAULT 0.00
);

在上面这条语句中,我们为 int 类型的 i 列指定了默认值 -1 ,为 varchar 类型的 c 列指定了默认值 '' ,为 double 类型的 price 列指定了默认值 0.00。也就是说,当我们插入数据的时候,并不需要完整的为每一列指定值。如果没有指定值,那么 MySQL 就会使用默认值填充。

但是,DEFAULT 约束有有一个特例,就是 SERIAL DEFAULT VALUE。等于类型为整形的列,它的作用相当于 NOT NULL AUTO_INCREMENT UNIQUE

其实这不怪 DEFAULT ,是 SERIAL 的锅。

但是,default 并不是没有 bug,显式 DEFAULT 约束处理的某些方面依赖于版本。

MySQL 8.0.13 中处理显式默认值

DEFAULT 约束中指定的默认值可以是文字常量或表达式。

如果使用表达式作为默认值,则需要表达式默认值括在括号内 () ,以将它们与文字常量默认值区分开来。

例如

CREATE TABLE t1 (
  -- 常量默认值
  i INT         DEFAULT 0,
  c VARCHAR(10) DEFAULT '',
  -- 表达式默认值
  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())
);

但是,这有一个例外。这个例外就是: TIMESTAMPDATETIME 列。

对于 TIMESTAMPDATETIME 列,我们可以将 CURRENT_TIMESTAMP 函数指定为默认值,而需要添加括号。

CREATE TABLE t1 (
  -- 常量默认值
  c TIMESTAMP         DEFAULT CURRENT_TIMESTAMP,
  u DATETIME          DEFAULT CURRENT_TIMESTAMP,
);

有关 TIMESTAMPDATETIME 列的详细内容,可以访问 傻傻分不清的 DATE、DATETIME 和 TIMESTAMP ( 上 )

而对于 BLOBTEXTGEOMETRYJSON 数据类型,只有在将值写为表达式时,才能分配默认值,即使表达式值是文字也是如此。

例如,下面这种写法是允许的,也就是使用文字字面量表达式

CREATE TABLE t2 (b BLOB DEFAULT ('abc'));

但下面这种写法则是不允许的,因为它是一个字面量而不是一个表达式

CREATE TABLE t2 (b BLOB DEFAULT 'abc');

表达式默认值必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误

  • 允许使用文字,内置函数(确定性和非确定性)和运算符
  • 不允许使用子查询,参数,变量,存储函数和用户定义的函数
  • 表达式默认值不能依赖于具有 AUTO_INCREMENT 属性的列。
  • 某一列的表达式默认值可以引用另外一张表中的列,但是对生成的列或具有表达式默认值的列的引用必须是对于在表定义中较早出现的列。也就是说,表达式默认值不能包含对生成的列或具有表达式默认值的列的前向引用。翻译成白话文就是,引用的列必须已经存在。

  • 排序 ( ordering ) 约束也适用于使用 ALTER TABLE 重新排序表列。如果结果表的表达式默认值包含对具有表达式默认值的生成列或列的前向引用,则该语句将失败

注意: 如果表达式默认值的任何组件取决于 SQL 模式,则表的不同用法可能会出现不同的结果,除非在所有使用过程中 SQL 模式都相同

对于语句 CREATE TABLE ... LIKECREATE TABLE ... SELECT ,目标表保留原始表中的表达式默认值。

如果表达式默认值引用非确定性函数,则导致表达式计算的任何语句对于基于语句的复制都是不安全的。包括 INSERTUPDATEALTER TABLE 等语句

插入新行时,可以通过省略列名或将列指定为 DEFAULT 来插入具有表达式 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 类型转换规则对声明的类型进行隐式强制。

MySQL 8.0.13 之前的版本中处理显式默认值

MySQL 8.0.13 之前的版本,DEFAULT 约束中指定的默认值必须是文字常量,而不能是一个函数或表达式。

但有一个例外,这个例外就是: TIMESTAMPDATETIME 列。

这意味着,我们不能将 date 列的默认值设置为函数的值,例如 NOW()CURRENT_DATE

而对于 BLOBTEXTGEOMETRYJSON 数据类型,根本就不允许分配默认值。

同样的,如果默认值的计算结果与声明的列类型不同,则根据通用的 MySQL 类型转换规则对声明的类型进行隐式强制。

处理隐式默认值

如果在定义表结构时不使用 DEFAULT 约束为列显式定义默认值,MySQL 将自己决定如何设置默认值。

  • 如果列可以将 NULL 作为值,则会使用显式的 DEFAULT NULL 子句定义该列。其实不用显式,因为它就是默认的定义。
  • 如果列不能将 NULL 作为值,则 MySQL 会定义没有显式 DEFAULT 子句的列。也就是并不会添加 DEFAULT 约束。

但这两条规则有一个例外,如果列被定义为 PRIMARY KEY 的一部分但未显式设置为 NOT NULL,则 MySQL 将其创建为 NOT NULL 列( 因为PRIMARY KEY 列必须为 NOT NULL )。

对于没有显式 DEFAULT 约束的 NOT NULL 列的数据输入,如果 INSERTREPLACE 语句不包含该列的值,或者 UPDATE 语句将列设置为 NULL ,MySQL 会根据当时生效的 SQL 模式处理列:

  • 如果启用了严格的 SQL 模式,则事务表会发生错误,并且会回滚 SQL 语句。对于非事务性表,会发生错误,但如果多行语句的第二行或后续行发生这种情况,则前面的行会正常插入。

  • 如果未启用严格模式,MySQL 会将列设置为列数据类型的隐式默认值

对于这段叙述,总觉得很拗口,好不,我们举个例子来说明下,假设表 t 定义如下

CREATE TABLE t (i INT NOT NULL);

上面这个表定义语句中,我们并没有为 i 字段显式的定义默认值,因此在严格模式下,以下每个语句都会产生错误,并且不会插入任何行。

INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));

不使用严格模式时,只有第三个语句产生错误,因为前两个语句插入了隐式默认值,但第三个语句失败,因为 DEFAULT(i) 无法生成值。

对于给定的表,我们可以使用 SHOW CREATE TABLE 语句显示哪些列具有显式 DEFAULT 约束。

而对于隐式默认值,则定义如下

  • 对于数字类型,默认值为 0,但对于使用 AUTO_INCREMENT 属性声明的整数或浮点类型,默认值是序列中的下一个值。

  • 对于 TIMESTAMP 以外的日期和时间类型,默认值为该类型的相应 「 零 」 值。如果启用了 explicit_defaults_for_timestamp 系统变量,那么 TIMESTAMP 类型的列的默认值也是 「 零 」 值。否则,对于表中的第一个 TIMESTAMP 列,默认值为当前日期和时间。

  • 对于 ENUM 以外的字符串类型,默认值为空字符串 ( "")。对于 ENUM 类型,默认值是第一个枚举值

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL拾遗之数据类型的默认值-default 的相关文章

  • 从 datagridview 选定的行更新 mysql 数据库

    我有一个 datagridview 它在表单加载事件上加载 mysql 数据库表 t pi clients 并且我有另一个选项卡 其中包含 t pi client 相应列的文本框 它能够从 fullrowselect 模式获取数据到这些文本
  • 子查询与连接

    我重构了从另一家公司继承的应用程序的一个缓慢部分 以使用内部联接而不是子查询 例如 WHERE id IN SELECT id FROM 重构后的查询运行速度提高了约 100 倍 50 秒到 0 3 我预计会有改进 但谁能解释为什么它如此剧
  • MySql JOINS 的优点/缺点

    当我从多个表中选择数据时 我经常使用 JOINS 最近我开始使用另一种方式 但我不确定从长远来看会产生什么影响 例子 SELECT FROM table 1 LEFT JOIN table 2 ON table 1 column table
  • mysql中的按位移位

    如何在 MySQL 中进行按位移位 有没有具体的指令或者操作符 如果不是 如何最佳地模拟它 看一下按位运算符MySQL first http dev mysql com doc refman 5 0 en bit functions htm
  • 是否可以在MYSQL中动态选择列名,其中列名是N个已知值中的1?

    我担心答案会是直接的 不 但我想知道是否可以在 MySQL 中执行如下操作 SELECT title label name FROM table 即选择单个列 可以称为title label or name from table 原因是 查
  • MYSQL 查询 WHERE IN 与 OR

    我开发了一个使用 OR 查询的系统 SELECT FROM tableA JOIN tableB ON idA idB WHERE idA 1 OR idA 2 OR idA 3 OR idA 4 OR idA 5 OR idA 100 与
  • 为什么涉及用户变量的表达式的求值顺序未定义?

    From MySQL手册 http dev mysql com doc refman 5 7 en user variables html以下查询的输出不保证始终相同 SET a 0 SELECT a AS first a a 1 AS s
  • 更新\插入数据从grafana到mysql

    可以从grafana更新数据或插入数据到mysql 我需要使用 UI 在 mysql 中插入 更新信息 现在我已经在使用grafana 所以想知道是否有任何方法可以使用grafana来更新或插入信息 没有用于获取用户输入并将该数据插入 My
  • 从所有表中选择

    我的数据库中有很多表都具有相同的结构 我想从所有表中进行选择 而不必像这样列出所有表 SELECT name FROM table1 table2 table3 table4 我尝试过 但这不起作用 SELECT name FROM 有没有
  • 如何使用MySqlCommand和prepare语句进行多行插入?(#C)

    Mysql 给出了如何使用准备语句和 NET 插入行的示例 http dev mysql com doc refman 5 5 en connector net programming prepared html http dev mysq
  • 使用 DBCP 配置 Tomcat

    在闲置一段时间 几个小时 后 我们收到了 CommunicationsException 来自 DBCP 错误消息 在异常中 位于这个问题的末尾 但我没有看到任何配置文件中定义的 wait timeout 我们应该看哪里 在 tomcat
  • MySQL Workbench 忽略外键

    在处理 MySQL Workbench 中的 SQL 编辑器时 我偶然发现了一些奇怪的事情 其中 执行似乎忽略了外键约束 这是一个例子 create database testdb use testdb create table t1 te
  • 如何解决 注意:未定义索引:第 21 行 C:\xampp\htdocs\invmgt\manufactured_goods\change.php 中的 id [重复]

    这个问题在这里已经有答案了 我的 PHP 代码有一个问题 显示 注意 未定义的索引 我确信它非常简单 因为我是初学者 所以我不太清楚到底出了什么问题 所以请帮助我 这是代码
  • 如何检查 $row['column_name'] 是否返回空 php mysql

    我有一个带有列的表格 id name phone describe 当我从这个表中获取值时 我正在使用 row mysql fetch array query 现在我想检查是否 row describe 返回空值 如何查看php 您可以使用
  • MySQL 跨表计数(*) 查询帮助

    SELECT name COUNT AS count FROM t1 t2 WHERE t2 id t1 id GROUP BY t2 id 我想从 t1 获取名称以及 t2 中 id 与 t1 相同的行数 到目前为止我已经得到了上面的内容
  • 使用数据库进行日志记录

    大多数日志似乎都是纯文本形式 而不是放入 MySQL 其他类型的数据库中 这是否有原因 在我看来 将它们放入数据库将使分析变得非常非常容易 但这会以牺牲速度还是其他什么为代价 我不太关心可移植性 显然你会有数据库连接的文本日志 我能想到两大
  • php无法在docker-compose中连接到mysql

    这是我的 docker compose version 2 services nginx image nginx 1 11 8 alpine ports 8081 80 volumes code usr share nginx html h
  • 对于相同的查询,MySQL Workbench 比 Python 快得多

    MySQL Workbench 中的以下查询需要 0 156 秒才能完成 SELECT date time minute price id FROM minute prices WHERE contract id 673 AND TIMES
  • 如何将“mysql source”命令与 mysql 变量一起使用?

    我需要从 mysql shell 执行一个基于如下条件的 SQL 文件 mysql gt 源 var 其中 var 包含文件名 这不可能 source是MySQL客户端程序在本地识别并执行的命令 变量存在于服务器上 因此客户端不知道什么 v
  • MySQL 复制是双向的

    我们已经成功设置了 MySQL 文献中描述的主从复制 不过 我很好奇是否有人设置了双向复制 例如 如果安装了 Drupal 或 Wordpress 第一个 主 数据库服务器出现故障 第二个 从属 数据库服务器恢复正常 与此同时 用户不断进行

随机推荐

  • 深度学习:实现mnist手写数字识别

    本文为 365天深度学习训练营 中的学习记录博客 原作者 K同学啊 接辅导 项目定制 我的环境 1 语言环境 Python 3 7 2 编译器 Pycharm 3 深度学习环境 TensorFlow2 5 一 前期工作 1 设置GPU 若使
  • Ubuntu20.04开机后,弹出检测到系统程序出现问题解决方法

    打开配置文件 sudo gedit etc default apport 然后 将其中的enable选项改成0 即可解决此问题
  • C++ *,&

    文章目录 语法 1 取地址运算符 2 间接寻址运算符 示例 1 可以累计使用间接寻址运算符来取消引用指向指针的指针 2 静态成员的地址 3 引用类型的地址 4 函数地址作为参数 4 示例 references 语法 1 取地址运算符 又称
  • c#量化交易_我用1天时间搭建自主量化交易(程序化交易)平台

    VirtualApi目前支持上海期货交易所的CTP回测 http www virtualapi cn 实盘期货 支持CTP http www kaihucn cn Simnow 上期CTP接口官方网站和模拟账户注册 http www sim
  • 【KITTI】KITTI数据集简介(一) — 激光雷达数据

    本文为博主原创文章 未经博主允许不得转载 本文为专栏 python三维点云从基础到深度学习 系列文章 地址为 https blog csdn net suiyingy article details 124017716 KITTI数据集的详
  • C++基础——new和delete动态开辟

    目录 前言 一 new关键字 格式2 动态开辟多个数据的堆区空间 数组 总结 二 自定义类型的开辟 1 区别 2 匹配错误讲解 错误示范例1 delete 的执行原理 错误示范2 三 malloc new失败的区别 1 malloc失败 2
  • 如何在WPS、MathType中输入傅立叶变换的符号

    这里写自定义目录标题 在MathType中 先输入大写F 选择上 然后在 mathtype 的 style Other 选择 Palace Script MT字体 如果没有该字体 选择Lucida Calligraphy字体 如果使用的是E
  • 设计模式-装饰模式

    装饰模式指的是在不必改变原类文件和使用继承的情况下 动态地扩展一个对象的功能 它是通过创建一个包装对象 也就是装饰来包裹真实的对象 在装饰模式中的各个角色有 抽象构件 Component 角色 给出一个抽象接口 以规范准备接收附加责任的对象
  • 启明智显分享

    据数据显示 全球新能源汽车销量正大幅度增长 全球汽车电动化渗透率也由0 8 增长到7 74 这不仅意味着汽车产业电动化浪潮的来临 也证实了我国新能源汽车行业正处于高速发展状态 随着电动汽车销售量与保有量的迅速增长 充电需求也持续攀升 在新基
  • php连接mysql代码

    php连接mysql的代码网上有很多 这里分享一个简单配置就能用的代码模板仅供参考
  • Ubuntu18中NVIDIA,cuda,cudnn,pytorch安装

    注意 nvidia驱动和cuda cudnn pytroch python的对应关系 linux安装pytorch 包括cuda与cudnn linux清华园按照pytorch1 12 BryceRui的博客 CSDN博客 安装流程 安装c
  • R手册(Visualise)--gganimate(ggplot2 extensions)

    文章目录 gganimate Create easy animations with ggplot2 返回ggplot2扩展主目录 gganimate Create easy animations with ggplot2 GitHub链接
  • SpringCloudAlibaba集成Sentinel

    什么是 Sentinel 随着微服务的流行 服务和服务之间的稳定性变得越来越重要 Sentinel 以流量为切入点 从流量控制 熔断降级 系统负载保护等多个维度保护服务的稳定性 Sentinel 的特征 丰富的应用场景 Sentinel 承
  • 游戏服务器稳定ping值,网友玩游戏时Ping值超过了2亿!

    经常玩网络游戏的朋友肯定都经历过延迟 太高的Ping值会使游戏体验惨不忍睹 但你见过超过2亿的Ping吗 这里简单介绍一下Ping 它是玩家客户端和游戏服务器之间的网络延迟 一般以毫秒 ms 作为单位 Ping越低 延迟越低 严重的延迟通常
  • 微信小程序项目使用npm安装vant-weapp的正确步骤及错误处理方法

    微信小程序项目使用npm安装vant weapp的正确步骤及错误处理方法 1 搭建小程序 1 1 项目 新建项目 如下图所示 1 2点击图中 新建 即可创建成功小程序项目 2 安装vant weapp库 2 0 在安装vant weapp之
  • ORA-01950: 对表空间 ‘SYSTEM‘ 无权限

    对表空间 SYSTEM 无权限 问题 对表空间 SYSTEM 无权限 处理 alter user test 用户名 quota unlimited on users 问题 对表空间 SYSTEM 无权限 出现ORA 01950 对表空间 S
  • QML-消息提示框

    QML 消息提示框 前言 一 提示框 二 警告提示框 三 错误提示框 四 属性介绍 前言 介绍常用的消息提示框 包括提示 错误 报警等 一 提示框 import QtQuick 2 12 import QtQuick Window 2 12
  • Qt creator出现mainwindow.ui does not exist,导致无法编译通过

    遇到这个问题 首先是之前做过删除ui mainwindow h的操作步骤 导致出现这样的问题 参考博客 https blog csdn net mhw828 article details 104143881 解决的方法就如这位博主说的 需
  • redis集群模式

    redis单机版 出现单机故障后 导致redis无法使用 如果程序使用redis 间接导致程序出错 redis的集群模式 主从复制模式 哨兵模式 集群化模式 1 主从复制模式 一主多从模式 一个主节点 多个从节点 那么主节点可以负责 读操作
  • MySQL拾遗之数据类型的默认值-default

    MySQL 中 所有的数据类型 都可以显式或隐式的拥有默认值 我们可以使用 DEFAULT 约束显式的为列指定一个默认值 比如 CREATE TABLE t1 i INT DEFAULT 1 c VARCHAR 10 DEFAULT pri