当前位置: 首页 > news >正文

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
http://www.jsqmd.com/news/794978/

相关文章:

  • 微信数据解密终极指南:快速恢复你的珍贵聊天记录
  • 终极指南:3分钟用纯C语言工具解锁网易云NCM加密音乐
  • 3分钟告别激活烦恼:Windows和Office智能激活完全指南
  • 终极BepInEx 6.0.0插件框架:从崩溃根源到稳定运行的完整解决方案
  • Fate/Grand Automata:基于计算机视觉的FGO自动化战斗解决方案
  • 大润发购物卡回收:解决闲置痛点,解锁多重实在好处 - 米米收
  • Mac窗口置顶神器Topit:告别窗口遮挡,打造高效工作流
  • 教育康复学考研辅导班推荐:专门针对性培训机构评测 - michalwang
  • 静态动态文件
  • B站视频如何高效下载?这个工具让你轻松保存4K超清内容
  • 火山引擎OpenViking镜像:云原生开发的高效基础与安全实践
  • 避震不是“越硬越好”:拆解阻尼、弹簧与预载的黄金三角法则
  • 南京假发定制品牌实测排行:工艺与口碑双维度解析 - 资讯焦点
  • 2026年佛山五金配件定制供应商横评:如何避开交期延误、小单被拒、品质波动三大坑 - 优质企业观察收录
  • 畜牧学考研辅导班推荐:专门针对性培训机构评测 - michalwang
  • Typora 很好,但我要的它给不了——所以我用 Rust 写了自己的 WYSIWYG 编辑器
  • Nigate:Mac用户的终极NTFS解决方案,三步实现跨平台文件自由
  • 暗黑3自动化战斗终极指南:D3KeyHelper鼠标宏工具完全掌握手册
  • 在 Node.js 后端服务中集成 Taotoken 调用大模型
  • 如何在绝地求生中使用罗技鼠标宏实现精准压枪:终极完整指南 [特殊字符]
  • 2026年广东狐臭医生口碑榜:三甲公立专业治疗深度实测拆解 - 速递信息
  • SQL线索
  • 射频电路电源与接地设计的关键技术与实践
  • C++ 管理类使用单例模式的特点与最佳实践
  • 3个场景告诉你:如何用DRG存档编辑器解锁《深岩银河》的终极体验
  • 实战开发人事管理系统:从需求到部署,新手也能落地的后端项目
  • 软件工程入门|初识软件工程的核心价值与开发模型
  • 放射医学考研辅导班推荐:专门针对性培训机构评测 - michalwang
  • AI写专著全攻略:从构思到完稿,快速生成20万字专著
  • C#循环入门指南:从0到1掌握循环逻辑