MySQL和Oracle虽然都遵循SQL标准,但在具体语法上存在不少差异。以下是主要的语法区别:
MySQL:
SELECT * FROM table_name LIMIT 10 OFFSET 20;
或
SELECT * FROM table_name LIMIT 20, 10;
Oracle:
-- 12c以下版本
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM table_name ORDER BY column_name
) a WHERE ROWNUM <= 30
) WHERE rn > 20;
-- 12c及以上版本
SELECT * FROM table_name OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
MySQL:
SELECT CONCAT('Hello', ' ', 'World');
或使用||(需设置SQL模式)
Oracle:
SELECT 'Hello' || ' ' || 'World' FROM dual;
MySQL:
SELECT NOW(); -- 当前日期时间
SELECT CURDATE(); -- 当前日期
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY);
SELECT DATEDIFF('2023-12-31', '2023-01-01');
Oracle:
SELECT SYSDATE FROM dual; -- 当前日期时间
SELECT CURRENT_DATE FROM dual; -- 当前日期
SELECT ADD_MONTHS(SYSDATE, 1) FROM dual;
SELECT TO_DATE('2023-12-31', 'YYYY-MM-DD') - TO_DATE('2023-01-01', 'YYYY-MM-DD') FROM dual;
MySQL:
SELECT IFNULL(column_name, 'default') FROM table_name;
或
SELECT COALESCE(column_name, 'default') FROM table_name;
Oracle:
SELECT NVL(column_name, 'default') FROM table_name;
或
SELECT COALESCE(column_name, 'default') FROM table_name;
MySQL:
CREATE TABLE table_name (
id INT AUTO_INCREMENT PRIMARY KEY,
...
);
Oracle:
CREATE TABLE table_name (
id NUMBER GENERATED ALWAYS AS IDENTITY,
...
);
-- 或使用序列
CREATE SEQUENCE seq_name;
CREATE TRIGGER trig_name BEFORE INSERT ON table_name
FOR EACH ROW BEGIN
SELECT seq_name.NEXTVAL INTO :NEW.id FROM dual;
END;
数据类型 | MySQL | Oracle |
---|---|---|
整数 | INT, INTEGER | NUMBER(10) |
字符串 | VARCHAR(n) | VARCHAR2(n) |
大文本 | TEXT, LONGTEXT | CLOB |
二进制大对象 | BLOB, LONGBLOB | BLOB |
布尔 | TINYINT(1)或BOOLEAN | NUMBER(1) |
获取当前用户:
SELECT USER();
SELECT USER FROM dual;
条件判断:
IF(condition, true_value, false_value)
CASE WHEN condition THEN true_value ELSE false_value END
MySQL(InnoDB引擎):
START TRANSACTION;
-- SQL语句
COMMIT; 或 ROLLBACK;
Oracle:
SET TRANSACTION; -- 可选
-- SQL语句
COMMIT; 或 ROLLBACK;
MySQL: 可以直接执行不带FROM的SELECT
SELECT 1 + 1;
Oracle: 需要使用DUAL伪表
SELECT 1 + 1 FROM dual;
这些差异在实际开发中需要特别注意,特别是在迁移数据库或编写跨数据库兼容的SQL时。