news 2026/5/11 9:45:05

SQL示例:分别使用 MySQL 和 Oracle 创建表(自增主键、指定主键的区别,VARCHAR,VARCHAR2)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL示例:分别使用 MySQL 和 Oracle 创建表(自增主键、指定主键的区别,VARCHAR,VARCHAR2)

本文介绍了创建actor表的SQL语句实现方案,重点对比了MySQL和Oracle两种数据库的语法差异。


MySQL版本使用SMALLINT主键、VARCHAR字段和CURDATE()默认值,而Oracle使用NUMBER类型、VARCHAR2字段和SYSDATE默认值。


文章详细说明了主键约束、默认值设置和字段注释的实现方式,并提供了低版本MySQL的替代方案(使用触发器)。


同时对比了自增主键和指定主键的特点,包括定义方式、唯一性保证、插入语法等维度,最后给出了不同场景下的主键选择建议。


对于需要兼容多版本或特殊需求的场景,还提供了混合方案的实现示例。


Oracle 特有VARCHAR2,其他数据库使用 VARCHAR。


题目:创建表

SQL232 创建一个actor表,包含如下列


描述

创建一个actor表,包含如下列信息

列表类型是否为NULL含义
actor_idsmallint(5)not null主键id
first_namevarchar(45)not null名字
last_namevarchar(45)not null姓氏
last_updatedatenot null最后更新时间,默认是系统的当前时间

解法


创建 actor 表的 MySQL 语句如下:


sql

CREATE TABLE actor ( actor_id SMALLINT(5) NOT NULL COMMENT '主键id', first_name VARCHAR(45) NOT NULL COMMENT '名字', last_name VARCHAR(45) NOT NULL COMMENT '姓氏', last_update DATE NOT NULL DEFAULT (CURDATE()) COMMENT '最后更新时间,默认是系统的当前时间', PRIMARY KEY (actor_id) );

说明:

  1. 主键约束actor_id被设置为主键,确保每行数据的唯一性

  2. 默认值last_update字段使用DEFAULT (CURDATE())设置默认值为当前系统日期(年月日部分)

  3. 注释使用COMMENT为每个字段添加了中文说明

注意:

  • DEFAULT (CURDATE())语法要求MySQL 8.0.13及以上版本

  • 如果使用更低版本的 MySQL,需要使用触发器来实现默认当前日期,或者改用DEFAULT CURRENT_DATE(但 MySQL 的 DATE 类型字段不支持直接使用CURRENT_DATE作为默认值)

兼容低版本 MySQL 的替代方案:

sql

CREATE TABLE actor ( actor_id SMALLINT(5) NOT NULL COMMENT '主键id', first_name VARCHAR(45) NOT NULL COMMENT '名字', last_name VARCHAR(45) NOT NULL COMMENT '姓氏', last_update DATE NOT NULL COMMENT '最后更新时间', PRIMARY KEY (actor_id) ); -- 创建触发器自动设置 last_update 的默认值 DELIMITER $$ CREATE TRIGGER actor_default_last_update BEFORE INSERT ON actor FOR EACH ROW BEGIN IF NEW.last_update IS NULL THEN SET NEW.last_update = CURDATE(); END IF; END$$ DELIMITER ;

完整建表+插入数据

  • 用 INSERT INTO ... VALUES 语法
  • 多条数据用逗号分隔,每条数据用括号包裹
  • 字段顺序与 VALUES 中的值顺序对应
  • 字符串和日期时间值使用单引号包裹

错误示例

--建表 CREATE TABLE IF NOT EXISTS actor ( actor_id smallint(5) NOT NULL PRIMARY KEY, first_name varchar(45) NOT NULL, last_name varchar(45) NOT NULL, last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')) ); --批量插入数据 INSERT INTO actor (actor_id, first_name, last_name, last_update) VALUES (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), (2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33'); --查询验证 SELECT * FROM actor;

注意

上例在 MySQL 中使用了 SQLite 的语法datetime('now','localtime'),MySQL 不支持这种写法。


-- ❌ 错误:这是 SQLite 的语法,MySQL 不支持 last_update timestamp NOT NULL DEFAULT (datetime('now','localtime')) -- ✅ MySQL 正确写法 last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP

正确的 MySQL 代码

-- 建表 CREATE TABLE IF NOT EXISTS actor ( actor_id smallint(5) NOT NULL PRIMARY KEY, first_name varchar(45) NOT NULL, last_name varchar(45) NOT NULL, last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); -- 批量插入数据 INSERT INTO actor (actor_id, first_name, last_name, last_update) VALUES (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), (2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33'); -- 查询验证 SELECT * FROM actor;

如果需要 DATETIME 类型

-- MySQL 5.6.5 之后版本支持 last_update DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -- 或使用函数 last_update DATETIME NOT NULL DEFAULT (NOW())

使用INSERT IGNORE语法来实现"如果数据已经存在,请忽略"

不使用replace操作

INSERT IGNORE INTO actor (actor_id, first_name, last_name, last_update) VALUES (3, 'ED', 'CHASE', '2006-02-15 12:34:33');

说明

关键字作用
INSERT IGNORE插入时如果主键冲突,忽略该条插入,不报错

执行逻辑

  1. 表中已存在actor_id = 3的记录(WD, GUINESS)

  2. 执行INSERT IGNORE尝试插入相同actor_id的记录

  3. 由于主键冲突,MySQL忽略新数据的插入

  4. 表中数据保持不变,仍为:3|WD|GUINESS|2006-02-15 12:34:33

其他替代方案(MySQL 语法对比)

语法行为适用场景
INSERT IGNORE冲突时忽略,不报错✅ 本题要求
REPLACE冲突时删除旧记录再插入新记录❌ 题目不支持
ON DUPLICATE KEY UPDATE冲突时执行更新操作需要更新时使用

在 Oracle 中实现相同的 actor 表,语法如下:


方法一:使用 DEFAULT 子句(推荐)

sql

CREATE TABLE actor ( actor_id NUMBER(5) NOT NULL, first_name VARCHAR2(45) NOT NULL, last_name VARCHAR2(45) NOT NULL, last_update DATE DEFAULT SYSDATE NOT NULL, CONSTRAINT pk_actor PRIMARY KEY (actor_id) ); COMMENT ON TABLE actor IS '演员表'; COMMENT ON COLUMN actor.actor_id IS '主键id'; COMMENT ON COLUMN actor.first_name IS '名字'; COMMENT ON COLUMN actor.last_name IS '姓氏'; COMMENT ON COLUMN actor.last_update IS '最后更新时间,默认是系统的当前时间';

方法二:使用触发器(更灵活的默认值)

如果需要只存储日期部分(不包含时间),可以使用触发器:

sql

-- 创建表 CREATE TABLE actor ( actor_id NUMBER(5) NOT NULL, first_name VARCHAR2(45) NOT NULL, last_name VARCHAR2(45) NOT NULL, last_update DATE NOT NULL, CONSTRAINT pk_actor PRIMARY KEY (actor_id) ); COMMENT ON TABLE actor IS '演员表'; COMMENT ON COLUMN actor.actor_id IS '主键id'; COMMENT ON COLUMN actor.first_name IS '名字'; COMMENT ON COLUMN actor.last_name IS '姓氏'; COMMENT ON COLUMN actor.last_update IS '最后更新时间,默认是系统的当前时间'; -- 创建触发器设置默认值 CREATE OR REPLACE TRIGGER trg_actor_last_update BEFORE INSERT ON actor FOR EACH ROW BEGIN IF :NEW.last_update IS NULL THEN :NEW.last_update := TRUNC(SYSDATE); -- TRUNC 去除时间部分,只保留日期 END IF; END; /

方法三:使用 identity 列(Oracle 12c+)

如果需要自增主键,可以使用 identity 列:

sql

CREATE TABLE actor ( actor_id NUMBER(5) GENERATED BY DEFAULT AS IDENTITY NOT NULL, first_name VARCHAR2(45) NOT NULL, last_name VARCHAR2(45) NOT NULL, last_update DATE DEFAULT SYSDATE NOT NULL, CONSTRAINT pk_actor PRIMARY KEY (actor_id) );

Oracle 与 MySQL 的主要差异:

项目MySQLOracle
整数类型SMALLINT(5)NUMBER(5)
字符串类型VARCHAR(45)VARCHAR2(45)
主键定义PRIMARY KEY (column)CONSTRAINT pk_name PRIMARY KEY (column)
当前日期时间CURDATE()SYSDATE
注释语法COMMENT '注释'COMMENT ON COLUMN...
只取日期部分CURDATE()TRUNC(SYSDATE)

建议:

  • 使用DEFAULT SYSDATE是最简单的方式,但会包含时间部分(00:00:00)

  • 如果严格只需要日期,使用TRUNC(SYSDATE)配合触发器

  • 如果需要自增主键,Oracle 12c 及以上版本使用IDENTITY


自增主键 vs 指定主键的区别

对比维度自增主键 (Auto-Increment)指定主键 (Assigned Primary Key)
定义方式MySQL:AUTO_INCREMENT
Oracle:IDENTITY或序列+触发器
直接赋值,如id = 100
值生成时机插入数据时由数据库自动生成插入前由应用程序或用户手动指定
唯一性保证数据库自动保证唯一,不会重复需要应用层或业务逻辑保证唯一
是否可为空通常配合 NOT NULL,插入时可省略该列必须明确赋值,不能为 NULL
插入语句INSERT INTO actor (name) VALUES ('Tom')
(省略主键列)
INSERT INTO actor (id, name) VALUES (101, 'Tom')
(必须指定主键值)
值含义仅表示记录的唯一标识,无业务含义可能代表业务含义(如身份证号、员工工号)
分布式系统容易产生冲突,需特殊处理(如雪花算法)适合分布式,可预先分配ID段
数据迁移可能产生冲突,需重置自增起始值可保持原有ID不变,迁移更简单
性能影响插入性能好,B+树顺序写入插入可能产生随机IO,性能略差
预测性无法提前预知新记录的ID可提前规划ID范围或规则
可读性无业务含义,仅用于内部关联可能有含义,如地区码+序号
修改灵活性通常不允许修改主键值理论上可修改,但不建议
适用场景无业务含义的代理键,绝大多数OLTP场景有业务含义的自然键,或需要外部系统指定ID

示例对比

操作自增主键指定主键
建表语句CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50))CREATE TABLE t (id INT PRIMARY KEY, name VARCHAR(50))
插入数据INSERT INTO t (name) VALUES ('Alice')
INSERT INTO t (name) VALUES ('Bob')
INSERT INTO t (id, name) VALUES (101, 'Alice')
INSERT INTO t (id, name) VALUES (102, 'Bob')
连续插入后结果id 自动为 1, 2, 3...id 保持指定的 101, 102...
插入已存在ID不会发生(自动生成新值)会报主键冲突错误

混合方案:默认自增 + 允许手动指定

某些数据库支持混合模式,设置默认自增但也可手动指定:

sql

-- MySQL: 允许手动指定覆盖自增值 INSERT INTO t (id, name) VALUES (100, 'Special'); -- 指定100 INSERT INTO t (name) VALUES ('Normal'); -- 自增为101 -- Oracle (12c+): CREATE TABLE t (id NUMBER GENERATED BY DEFAULT AS IDENTITY, name VARCHAR2(50)); -- 可手动指定或自动生成

选择建议

场景推荐方案
无业务需求的纯粹标识✅ 自增主键
主键有业务含义(如订单号)✅ 指定主键
数据来自多个系统或分库分表✅ 指定主键(如雪花ID)
需要频繁数据合并迁移✅ 指定主键
追求最高插入性能✅ 自增主键
希望主键对外不可预测✅ 指定主键(随机值)或使用UUID

VARCHAR vs VARCHAR2 区别

对比维度VARCHARVARCHAR2
数据库支持MySQL、PostgreSQL 等支持
Oracle 也支持但不推荐
Oracle 特有,其他数据库不支持
标准定义SQL 标准类型Oracle 私有类型(非标准)
存储空间相同(可变长度,实际长度+1~2字节)相同(可变长度,实际长度+1~2字节)
最大长度MySQL: 65535字节
Oracle: 4000字节
Oracle: 4000字节(12c后可达32767)
空字符串处理空字符串''等同于NULL空字符串''也等同于NULL(Oracle中相同)
官方推荐Oracle 官方不推荐使用VARCHAROracle 官方推荐使用VARCHAR2

核心结论

Oracle 中两者功能完全相同,但官方强制要求使用 VARCHAR2

Oracle 官方文档明确说明:

  • VARCHAR计划在未来版本中改变用途或废弃

  • 始终使用VARCHAR2确保向后兼容

跨数据库建议

数据库推荐类型
OracleVARCHAR2
MySQLVARCHAR
PostgreSQLVARCHAR
SQL ServerVARCHAR
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/11 9:40:35

IDEA安装个人开发插件

写了个idea插件打成jar包后进入插件然后点设置从磁盘安装插件选择自己jar包路径重启就行

作者头像 李华
网站建设 2026/5/11 9:38:33

怎样快速批量下载微博相册:免费高效工具完整指南

怎样快速批量下载微博相册:免费高效工具完整指南 【免费下载链接】Sina-Weibo-Album-Downloader Multithreading download all HD photos / pictures from someones Sina Weibo album. 项目地址: https://gitcode.com/gh_mirrors/si/Sina-Weibo-Album-Downloader…

作者头像 李华
网站建设 2026/5/11 9:38:31

像素映射天地 视频解构空间 ——以Pixel2Geo™核心技术,开启数字孪生与视频孪生无感感知新时代

像素映射天地 视频解构空间——以Pixel2Geo™核心技术,开启数字孪生与视频孪生无感感知新时代一、企业核心定位:无感感知赛道开创者,实景孪生技术定义者镜像视界(浙江)科技有限公司深耕数字孪生与视频孪生领域底层创新…

作者头像 李华
网站建设 2026/5/11 9:36:47

如何用GetQzonehistory一键备份你的QQ空间历史记录:完整指南

如何用GetQzonehistory一键备份你的QQ空间历史记录:完整指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 还在为QQ空间里那些珍贵的青春回忆担心吗?GetQzoneh…

作者头像 李华
网站建设 2026/5/11 9:36:05

WorkshopDL:打破平台壁垒的终极Steam创意工坊下载解决方案

WorkshopDL:打破平台壁垒的终极Steam创意工坊下载解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否曾在Epic Games Store或GOG平台购买了心仪的游戏&a…

作者头像 李华
网站建设 2026/5/11 9:35:45

Rust构建LLM应用流水线:llm-chain框架实战指南

1. 项目概述:用Rust构建你的LLM应用流水线如果你正在用Rust捣鼓大语言模型(LLM)应用,比如想做个智能客服、一个能自动处理文档的Agent,或者任何需要多步推理的复杂任务,那你大概率遇到过这样的困境&#xf…

作者头像 李华