---
globs: ["**/*.sql", "**/oracle/**", "**/plsql/**", "**/mapper/**"]
---

# Oracle 数据库规范

## 版本与基本信息
- 版本：Oracle {{ORACLE_VERSION}}
- 默认事务隔离级别：读已提交（Read Committed）

## 命名规范
- 命名使用大写英文字母、数字、下划线，以字母开头
- 对象名不超过 30 个字符（Oracle 限制）
- 命名使用有意义的英文词汇，下划线分隔

## 表设计规范
- 表必备 6 字段：`id`（主键，使用项目发号器）、`create_time`、`update_time`、`create_id`、`update_id`、`is_deleted`（1=删除，0=正常）
- DO 类属性类型必须与 Oracle 字段类型匹配：`NUMBER` 对应 Java `Long` 或 `BigDecimal`
- Oracle 的 `DATE` 类型包含年月日时分秒（与 MySQL 的 DATE 不同）
- 禁止使用 `CLOB/BLOB/NCLOB`，文件存文件系统，数据库只存路径

## 语法差异（区别于 MySQL）
- Oracle 没有 `LIMIT/OFFSET`，分页必须使用 `ROWNUM` 子查询
- Oracle 没有 `AUTO_INCREMENT`，自增字段必须创建 Sequence
- `FROM` 后面禁止使用 `AS` 别名（如 `FROM table AS t` 会报错），直接写 `FROM table t`
- 没有表时 SELECT 必须加 `FROM DUAL`，如 `SELECT 1 FROM DUAL`
- 字符串连接使用 `||` 运算符，Oracle 的 `CONCAT` 只能连接两个字符串

## 数据类型与函数映射

| 用途 | MySQL | Oracle |
|------|-------|--------|
| 自增主键 | `AUTO_INCREMENT` | `NUMBER(19,0)` + Sequence |
| 当前时间 | `NOW()` | `SYSDATE` |
| 字符串转日期 | `STR_TO_DATE()` | `TO_DATE()` |
| 日期转字符串 | `DATE_FORMAT()` | `TO_CHAR()` |
| 空值判断 | `IFNULL()` | `NVL()` |
| 条件判断 | `IF()` | `CASE WHEN`（推荐）或 `DECODE` |
| 分页 | `LIMIT offset, count` | `ROWNUM` 子查询 |

## SQL 规范
- `SELECT` 必须指定具体字段，禁止 `SELECT *`
- `INSERT` 必须指定具体字段
- 所有 DML（除 INSERT）必须有 WHERE 条件且使用索引
- WHERE 条件字段类型必须一致，杜绝隐式类型转换
- WHERE 字段上禁止使用函数转换，只能转换代入值
- 禁止使用 `NOW()/RAND()/SYSDATE()/CURRENT_USER()` 等不确定函数做插入更新
- `IN` 集合元素不超过 1000，超过使用子查询或拆分
- 减少 `OR`，优化为 `UNION ALL`
- 使用 `EXPLAIN PLAN FOR` 分析执行计划，确保索引被正确使用
- 大表（超千万行）必须特别注意索引设计和 SQL 优化

## 事务规范
- 批量更新每次不超过 1000 条记录，做到少量多次并适当 sleep
- 事务方法必须是 `public` 的（Spring AOP 限制）
- 同类内部方法调用不会触发事务，需通过代理调用
- 默认只有 `RuntimeException` 和 `Error` 触发回滚，检查型异常需在 `@Transactional` 中指定
- 并发修改同一记录使用乐观锁（`version` 字段）

## 禁用项
- 禁止使用存储过程
- 禁止使用外键与级联
- 禁止使用 `CLOB/BLOB/NCLOB`

## DAO 层设计建议
- 数据库连接必须有超时和失败重连机制，失败重试需有间隔
- 连接池必须配置初始/最小/最大连接数、超时时间和回收机制
- 设计阶段考虑并规避主从延迟对业务的影响
