工作中用到了oracle和mysql,所以如果sql有差异性就要提供两套。这篇文章来总结下oracle和mysql函数之间的区别、是否可替换。

一.Oracle的with x AS (子查询), y AS (子查询)…

这个语法很简单,可以认为是先创建了一(多)个临时结果集,再在后面使用这些结果集操作。其实就是公用表表达式(CTE)

WITH A AS(
SELECT USER_NAME,OFFICE_CODE FROM T_SYS_ACCOUNT_INFO
),B AS(SELECT OFFICE_CODE,OFFICE_NAME FROM T_SYS_OFFICE
)
SELECT A.USER_NAME,B.OFFICE_NAME FROM A LEFT JOIN B ON A.OFFICE_CODE=B.OFFICE_CODE;

效果:

上面的sql其实一个表连接就出来,只是作为一个简单的例子而已。实际场景应该是首先可能会查不同的表筛选一部分数据,最后再汇总这些数据再进行筛选查询,可读性很高。如果没有这样的语法,可能就是纯表连接查询,想想sql会有臃肿。mysql8才提供该语法。注意:with之后,要紧跟sql语句。

二.Oracle递归函数,connect by

基本语法:

select * from table [start with condition1]connect by [prior] id=parentid

1、 start with condition1 and condition2 or condition3…:代表从哪一(满足条件的)层级作为根节点开始查询
2、递归查询的方式。可以认为当前数据按照什么方式去查询下一层数据。例如,connect by prior id=parentid的意思就是当前数据的id当做下一层数据的parentid查询(查询儿子);connect by id=prior parentid的意思是当前数据的parentid是下一层数据的id(查询父亲)。
3、测试语法,准备数据:

(1)查询china所有子级数据:

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY START WITH CITY_CODE='000000' CONNECT BY PRIOR CITY_CODE=PARENT_CITY_CODE;

结果:

解析:①LEVEL关键字,查看数据所在的层数,1级就是根节点。②START WITH CITY_CODE=‘000000’ 把CITY_CODE='000000’的数据当做根节点(level为1)③CONNECT BY PRIOR CITY_CODE=PARENT_CITY_CODE,查询当前层级的CITY_CODE是下一层的PARENT_CITY_CODE的数据(当前层数数据的子级)

(2)查询浙江省杭州市的父级数据:

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY START WITH CITY_CODE='330100' CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE;

结果:

解析:①START WITH CITY_CODE='330100’把浙江省杭州市当做根节点 ②CONNECT BY CITY_CODE=PRIOR PARENT_CITY_CODE,当前层级的PARENT_CITY_CODE是下一层级的CITY_CODE(当前层级数据的父级)

(3)START WITH 多个条件,父级查询:

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY START WITH CITY_CODE='330100' OR CITY_CODE='330700'
CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE;

结果:

解析:可以看到结果是START WITH 满足条件的数据当做根节点(分开)查询
(4)把START WITH 换成WHERE 以及 没有START WITH 、WHERE,父级查询

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY WHERE CITY_CODE='330100' CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE;

结果:

why? 莫方,往下看,没有START WITH 和 WHERE:

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE;

结果:

解析:这两个情况结合来看,没有START WITH和WHERE的时候,其实就是把所有数据都当做根节点来查询;而有WHERE的时候,就是在上面情况筛选出符合条件的数据而已。
(5)趁热打铁,START WITH 和 WHERE同时存在的语法呢?效果是什么?父级查询

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY WHERE CITY_CODE='330000' START WITH CITY_CODE='330102'  CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE ;

结果:

根据(4)的解析和结果的level猜测,这个WHERE还是从递归查询结果筛选,去掉WHERE:

SELECT CITY_NAME,CITY_CODE,PARENT_CITY_CODE,LEVEL
FROM TEST_CITY  START WITH CITY_CODE='330102'  CONNECT BY  CITY_CODE=PRIOR PARENT_CITY_CODE ;

结果:

解析:CONNECT BY 和 WHERE 连用,效果是WHERE(后)在CONNECT BY(先)的结果再次筛选
4、小结:
(1)START WITH 可以有多个条件;效果其实就是先WHERE后递归查询
(2)如果有WHERE,只能放在START WITH之前,效果是先递归查询后WHERE
(3)①CONNECT BY PRIOR COLUNM_A= COLUNM_B,当前层级的COLUNM_A是下一层的COLUNM_B②CONNECT BY COLUNM_A=PRIOR COLUNM_B,当前层级的COLUNM_B是下一层的COLUNM_A
(4)遗憾的是,mysql并没有自带的递归查询函数,想要实现递归查询效果的话就是表关联或者自己写一个存储过程。

三.ORACLE和MYSQL时间、时间戳字段

1、向表里新增date、timestamp字段并添加字段说明:
(1)oracle:

ALTER TABLE TEST_CITY ADD (CREATE_DATE DATE,UPDATE_TIMESTAMP TIMESTAMP);
COMMENT ON COLUMN TEST_CITY.CREATE_DATE IS '创建时间,date';
COMMENT ON COLUMN TEST_CITY.UPDATE_TIMESTAMP IS '更新时间,timestamp';

(2)mysql:

ALTER TABLE test_city ADD(CREATE_DATE DATETIME COMMENT '创建时间,datetime',
UPDATE_TIMESTAMP TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间,timestamp');

解析:①oracle的timestamp类型的字段,新增的时候值可以为null;mysql不行 ②mysql的date类型只有年月日,datetime是年月日 时分秒。②mysql新增timestamp类型字段,(n)代保留毫秒数几位,最大6位。具体效果如图:

2、更新数据:
(1)oracle:

UPDATE TEST_CITY SET CREATE_DATE=TO_DATE('2019-11-25 15:23:55', 'YYYY-MM-DD HH24:mi:ss') WHERE CITY_CODE='000000';UPDATE TEST_CITY SET UPDATE_TIMESTAMP=TO_TIMESTAMP('2019-11-01 15:15:15', 'YYYY-MM-DD HH24:mi:ss') WHERE CITY_CODE='000000';

ORACLE添加date类型数据要使用到TO_DATE函数,timestamp类型用TO_TIMESTAMP函数。
(2)、mysql:

UPDATE TEST_CITY SET CREATE_DATE='2019-11-25 15:23:55' WHERE CITY_CODE='000000';UPDATE TEST_CITY SET UPDATE_TIMESTAMP='2019-11-01 15:15:15' WHERE CITY_CODE='000000';

没错,mysql就是这么爽,自动帮你转换时间类型!
3、格式化时间:
(1)oracle:

SELECT TO_DATE('2019-11-25 15:15:15', 'YYYY-MM-DD HH24:MI:SS') AS "DATE" FROM DUAL;
SELECT SYSDATE FROM DUAL;

结果:

sysdate查询当前时间的格式就是年-月-日 时:分:秒 不需要再to_date格式化
(2)mysql:mysql格式化时间详情,点我!

SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') AS "DATETIME";

结果:

4、顺便说一下删除字段:
(1)oracle:

ALTER TABLE TEST_CITY DROP (CREATE_DATE,UPDATE_TIMESTAMP);

(2)mysql:

ALTER TABLE TEST_CITY DROP CREATE_DATE,DROP UPDATE_TIMESTAMP;

5、再赠送一个小技巧吧,查询当前时间到n天之前之间的所有日期(多行)
(1)oracle:ROWNUM <= n是控制间隔天数的关键

SELECT TO_CHAR(SYSDATE-(ROWNUM-1), 'YYYY-MM-DD') DATE_TIME,ROWNUM
FROM DUAL
CONNECT BY
ROWNUM  <=  7;

效果:

(2)mysql:between date_sub(curdate(),interval n-1 day)是控制间隔天数的关键
mysql没有connect by语法,但是万能的网友总有办法:

select a.myDate AS DAY_TIME from ( select DATE_SUB(CURDATE(),interval (a.a + (10 * b.a))  day ) as myDate from(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a cross join (select 0 as a union all select 1 union all select 2 ) as b )awhere a.myDate between date_sub(curdate(),interval 7-1 day) and curdate();

效果:

四.oracle、mysql指定排序规则

前提背景:用户表有一个字段del_flag,0代表启用状态、1代表禁用,后来又加了一个特殊用户的状态,2申请中。现在的需求是查询出的数据,按照申请中>启用>禁用的顺序返回给前端。(如果刚开始就设计的1为启用状态,一个排序就ok了。o(╥﹏╥)o)
1、准备数据:为了更直观,加了一个字段显示状态的意思

2、测试开始:
(1)oracle:
个人的思路是查询的时候根据del_flag的值做一个操作生成一个新列,最后按照这个新列排序就好了:

SELECT NAME,DEL_FLAG,DEL_NAME,CASE WHEN DEL_FLAG =1 THEN 0 WHEN DEL_FLAG=0 THEN 1 ELSE DEL_FLAG END AS ORDERDELFLAG
FROM TEST_USER
ORDER BY ORDERDELFLAG DESC;

效果:

基本上很接近了,但是排序的时候ORACLE会把null认为是最大的值,ASC升序则排在最后,DESC降序则排在最前。可以指定null的位置:NULLS LAST:把null的值放最后。
修改sql:

SELECT NAME,DEL_FLAG,DEL_NAME,CASE WHEN DEL_FLAG =1 THEN 0 WHEN DEL_FLAG=0 THEN 1 ELSE DEL_FLAG END AS ORDERDELFLAG
FROM TEST_USER
ORDER BY ORDERDELFLAG DESC NULLS LAST;

效果:

ok,完美。
(2)mysql:
①方案一可以参考oracle,根据DEL_FLAG的值新增一列,再根据这一列排序。
②重点,mysql可以指定字段是什么值的时候在前面,指定字段值排序顺序:ORDER BY FIELD(COLUMN,VALUE1,VALUE2…),当字段的值为value1的时候最靠前,依此类推…

SELECT NAME,DEL_FLAG,DEL_NAME
FROM TEST_USER
ORDER BY FIELD(DEL_FLAG,2,0,1);

效果:

卧槽?效果很接近了,可以看到排序方式确实是按照DEL_FLAG值为2>0>1排序,但是这个null好烦人啊,排序时mysql会把null认为是最小的值
修改sql:

SELECT NAME,DEL_FLAG,DEL_NAME
FROM TEST_USER
ORDER BY FIELD(DEL_FLAG,1,0,2) DESC;

效果:

ok,完美!注意一点,FIELD已经是指定了排序,如果再加上DESC,实际是按照指定values相反顺序排序!
3、mysql使用FIELD特殊情况:新增两条数据

(1)value没有包含所有的值,如何排序?

SELECT NAME,DEL_FLAG,DEL_NAME
FROM TEST_USER
ORDER BY FIELD(DEL_FLAG,1,0,2);

结果:

FIELD升序,FIELD中没有指定的值,在指定的值之前排序展示

SELECT NAME,DEL_FLAG,DEL_NAME
FROM TEST_USER
ORDER BY FIELD(DEL_FLAG,1,0,2) DESC;

结果:

FIELD降序,FIELD中指定的值先展示->疑问来了,没有指定的值排序好像都是默认的排序规则,升序。
注意:2(2)②的情况实际是FILE降序,未指定排序的放到后面了(当然,认为最小的降序排后面也可以)
4、小结:
(1)mysql的FIELD(COLUMN,VALUE1,VALUE2…)可以按照匹配的顺序自定义排序顺序
(2)FIELD函数后面的排序方式只针对FIELD匹配到值的字段,未匹配到值的字段则默认升序
(3)FIELD升序时,未匹配到值的字段先展示;FIELD降序时,未匹配到值的字段后展示
(4)排序时mysql会把null认为是最小的值;oracle认为是最大的值
以后有时间在整理吧~

萌新发言,不喜勿喷,欢迎各位大佬指出不当之处!

ORACLE和MYSQL一些函数和实现效果的对比、替换相关推荐

  1. mysql oracle round,Oracle和MySQL的函数对比和常用区别

    编号类别ORACLEMYSQL注释1数字函数round(1.23456,4)round(1.23456,4)一样: ORACLE:select round(1.23456,4) value from ...

  2. Oracle转MySQL存储函数percentile_cont(比例) WITHIN GROUP( ORDER BY to_number(分数) )用法

    在Oracle中会用到 percentile_cont(比例) WITHIN GROUP( ORDER BY to_number(分数) ) 的写法,但在MySQL中却没有percentile_con ...

  3. oracle 分割取值,oracle中的分割函数(split效果)

    CREATE OR REPLACE FUNCTION fn_split (p_str IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN ty_str_split ...

  4. ORACLE和MYSQL函数

    函数 函数 编号 类别 ORACLE MYSQL 注释 1 数字函数 round(1.23456,4) round(1.23456,4) 一样: ORACLE:select round(1.23456 ...

  5. mysql rollup函数_Mysql,Oracle使用rollup函数完成行列统计

    昨天突然在 一篇博客中看到了Mysql也有rollup函数,原博文使用了rollup进行行列统计,原博文链接如下: 本博文主要是记录下mysql和oracle使用rollup函数进行行列统计,内容比较 ...

  6. mysql nextval同步锁_mysql中实现类似oracle中的nextval函数

    我们知道mysql中是不支持sequence的,一般是建表的时间使这个字段自增. 如       create table table_name(id int auto_increment prima ...

  7. oracle实现mysql的if_【原创】ORACLE的几个函数在MYSQL里面的简单实现

    david_yeung关注1人评论652人阅读2012-08-13 12:02:55 最忌在做ORACLE到MYSQL得迁移,以下我写了三个简单的MYSQL里面米有的函数. 供大家参考. 判断是否为时 ...

  8. oracle、sqlserver、mysql常用函数对比[to_char、to_number、to_date]

    oracle.sqlserver.mysql常用函数对比[to_char.to_number.to_date] oracle   -->    mysql to_char(sysdate,'yy ...

  9. mysql pmt函数,Mybatis中Oracle和Mysql的Count字段问题

    Mybatis中Oracle和Mysql的Count字段问题 我们在进行项目开发时经常会碰到查询总数的问题,所以我们直接是用select count(1) from table来进行查询.那么在Myb ...

最新文章

  1. 26_多线程_第26天(Thread、线程创建、线程池)_讲义
  2. 爬取猎聘python_爬取猎聘大数据岗位相关信息--Python
  3. SpringBoot @CachePut注解的使用原理
  4. Spring学习手册 1:Spring MVC 返回JSON数据
  5. 新乡学院2019计算机报名,新乡学院2019年招生章程
  6. android UI进阶之仿iphone的tab效果
  7. 关于建立内部会议讨论规范的想法
  8. 如何使用Java帮助文档
  9. ios 模糊搜索支持首字母搜索、拼音搜索、汉字搜索
  10. 目标建立——SMART法则
  11. moc3041光耦驱动bta12一直导通
  12. Node+puppeteer学习笔记 (二)--环境搭建Win、MAC、Linux环境,以及使用Sublime Text3运行
  13. Vin码采集,Vin码录入
  14. OpenCV + ORC 实现身份证识别
  15. 【unity-Max】A polygon of Mesh ‘XXX‘ in Assets/XXX/XXX.FBX is self-intersecting and has been discarded
  16. Mybatis-plus 代码生成器(新)
  17. aircrack-ng 添加Mac OS X 支持 airodump-ng和aireplay-ng都可以用了
  18. 关于影印版与翻译版的对比
  19. 侯捷C++视频笔记——C++面向对象高级编程(下)
  20. 萤石云C#方案,调用官方DLL SDK实现全部功能

热门文章

  1. 关于 Kubernetes中NetworkPolicy(网络策略)方面的一些笔记
  2. 基于verilog状态机的八层电梯实现
  3. Appops权限管理
  4. robotframework 中ride数据丢失且关键词无法高亮
  5. 西瓜书与蓝皮书 思维导图(转)
  6. HTB_Responder 综合靶机 菜菜被虐现场实录
  7. Python+OpenCV判断图像是黑底还是白底
  8. C/C++ 语言中.h文件和.c文件详细解析 引用 .c和.h文件的区别
  9. 人工智能α-β树剪支图文
  10. 转 Android屏幕适配全攻略(最权威的官方适配指导)