本文介绍了创建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主键idfirst_namevarchar(45)not null名字last_namevarchar(45)not null姓氏last_updatedatenot null最后更新时间默认是系统的当前时间解法创建 actor 表的 MySQL 语句如下sqlCREATE 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) );说明主键约束actor_id被设置为主键确保每行数据的唯一性默认值last_update字段使用DEFAULT (CURDATE())设置默认值为当前系统日期年月日部分注释使用COMMENT为每个字段添加了中文说明注意DEFAULT (CURDATE())语法要求MySQL 8.0.13及以上版本如果使用更低版本的 MySQL需要使用触发器来实现默认当前日期或者改用DEFAULT CURRENT_DATE但 MySQL 的 DATE 类型字段不支持直接使用CURRENT_DATE作为默认值兼容低版本 MySQL 的替代方案sqlCREATE 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插入时如果主键冲突忽略该条插入不报错执行逻辑表中已存在actor_id 3的记录WD, GUINESS执行INSERT IGNORE尝试插入相同actor_id的记录由于主键冲突MySQL忽略新数据的插入表中数据保持不变仍为3|WD|GUINESS|2006-02-15 12:34:33其他替代方案MySQL 语法对比语法行为适用场景INSERT IGNORE冲突时忽略不报错✅ 本题要求REPLACE冲突时删除旧记录再插入新记录❌ 题目不支持ON DUPLICATE KEY UPDATE冲突时执行更新操作需要更新时使用在 Oracle 中实现相同的 actor 表语法如下方法一使用 DEFAULT 子句推荐sqlCREATE 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 列sqlCREATE 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_INCREMENTOracle: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需要频繁数据合并迁移✅ 指定主键追求最高插入性能✅ 自增主键希望主键对外不可预测✅ 指定主键随机值或使用UUIDVARCHAR vs VARCHAR2 区别对比维度VARCHARVARCHAR2数据库支持MySQL、PostgreSQL 等支持Oracle 也支持但不推荐Oracle 特有其他数据库不支持标准定义SQL 标准类型Oracle 私有类型非标准存储空间相同可变长度实际长度1~2字节相同可变长度实际长度1~2字节最大长度MySQL: 65535字节Oracle: 4000字节Oracle: 4000字节12c后可达32767空字符串处理空字符串等同于NULL空字符串也等同于NULLOracle中相同官方推荐Oracle 官方不推荐使用VARCHAROracle 官方推荐使用VARCHAR2核心结论Oracle 中两者功能完全相同但官方强制要求使用 VARCHAR2Oracle 官方文档明确说明VARCHAR计划在未来版本中改变用途或废弃始终使用VARCHAR2确保向后兼容跨数据库建议数据库推荐类型OracleVARCHAR2MySQLVARCHARPostgreSQLVARCHARSQL ServerVARCHAR