SQL语法(一)

此SQL笔记为听网易云课堂李兴华老师的课程后整理的笔记,感谢李兴华老师,讲的很详细很系统。


格式化指令:

|-    SET LINESIZE 300;     //设置每行显示的数据长度,需右击命令框-属性-布局-两个宽度设置为120

|-    SET PAGESIZE 30;      //设置表格数据每页显示的最大长度

|-    COL列标题 FOR     A参数;     //设置某列显示长度为10

 

SQL下启动记事本程序:

|-    ed 文件名  //输入命令保存入记事本(文件后缀缺省值为.sql)

        |-    @文件名    //执行文本中的命令(文件后缀缺省值为.sql)

 

切换账号登录:

       |-    CONN用户名/密码 [AS SYSDBA]   //如果是使用sys账号登录,必须写上AS SYSDBA

       |-    showuser    //显示当前用户名

 

调用本地pc命令:

       |-    HOST 本地命令参数  //例:HOST copy d:\temp.txtd:\1.txt

 

scott用户表结构:

       |-    SELECT * FROM tab    //查询当前用户下的所有数据表

       |-    DESC 表名;           //查询一个数据表的结构

 

----------------------------------------------------------------------------------------------------------------

 

复杂查询=简单查询+限定查询+多表查询+分组统计查询+子查询。

 

 简单查询:

       |-    SELECT [DISTINCT] * FROM 表名称[别名] //DISTINCT:不显示重复项

       |-    SELECT[DISTINCT] 列名称 [别名],列名称 [别名]...FROM表名称[别名]以上结构,首先执行FROM字句,再执行SELECT字句。DISTINST去除重复项。

例1:SELECT * FORM EMP;  //查询EMP表中全部数据

例2:SELECT ENAME,JOB,SAL FROM EMP;             //查询EMP表中的指定数据(姓名,工作,工资)

例3:SELECT ENAME,JOB,SAL*12 SALYEAR FROM EMP;             //工资数据乘12,并设置为别名SALYEAR

       |-    SELECT列名称||列名称 [别名] FROM表名称//将多个列的内容合并为一个类显示(插入的字符串用“ ”声明)

              列:SELECT 'NAME:'||ENAME||',JOB:'||JOB||',SAL:'||SAL INFORMATION FROM EMP;            //合并输出 ”AME: 姓名,JOB:工作,SAL:工资” 的格式

 

---------------------------------------------------------------------------------------------------------------

 

限定查询:

        |-    SELECT [DISTINCT] *|列名称 [别名],列名称 [别名]... //③控制需要显示的列数据

FROM 表名称 [别名]          //①确定数据来源

[WHERE 过滤条件]   //②筛选满足条件的数据行

|-    关系运算符:>、<、>=、<=、<>(!=);

|-    逻辑运算符:AND、OR、NOT;

|-    范围运算符:BETWEEN...AND;

|-    谓词范围:  IN、NOTIN;      //NOT IN的查询范围内不允许出现NULL,否则返回查询结果NULL

|-    空判断:    IS NULL、ISNOT NULL;

|-    模糊查询:  LIKE。

        |-    “_”:匹配任意的一位字符

        |-    “%”:匹配任意的零位、一位、多位字符

例1:SELECT EMPNO,ENAME,JOB FROM EMP WHERE JOB!='SALESMAN' AND JOB!='CLERK';

例2:SELECT * FROM EMP WHERE JOB='SALESMAN' OR SAL>=2000;

例3:SELECT * FROM EMP WHERE HIREDATE BETWEEN '01-1月-81' AND '31-12月-1981';

例4:SELECT *FROM EMP WHERE EMPNO IN(7499,7782,7900,9999);

例5:SELECT *FROM EMP WHERE COMM IS NOT NULL;

例6:SELECT * FROM EMP WHERE ENAME LIKE '_A%'; //姓名第二位为A

 

---------------------------------------------------------------------------------------------------------------

 

排序查询:

       |-    SELECT [DISTINCT] *|列名称 [别名],列名称 [别名]... //③控制需要显示的列数据

FROM 表名称 [别名]          //①确定数据来源

[WHERE 过滤条件]        //②筛选满足条件的数据行

               [ORDER BY 字段 [ASC|DESC],字段 [ASC|DESC],      ...    ] //④排序,ASC(缺省默认):升序排列,DESC:降序排列。SQL语句中只有ORDER BY可以调用SELECT字句中的别名

例1:SELECT *FROM EMP WHERE JOB='SALESMAN' ORDER BY SAL DESC,HIREDATE ASC;

例2:SELECT EMPNO,ENAME,SAL*12 INCOME FROM EMP ORDER BY INCOME;

 

-----------------------------------------------------------------------------------------------------------------

 

单行函数:       //完成某一功能的操作函数,例:转大小写、日期格式转换等

       |-    字符串函数

函数

返回值

功能

UPPER(列|字符串)

String

将传入的字符串变为大写

LOWER(列|字符串)

String

将传入的字符串变为小写

INITCAP(列|字符串)

String

开头首字母大写,其余字母小写

LENGTH(列|字符串)

Int

取得指定字符串的长度

SUBSTR(列|字符串,开始索引[,长度]

String

进行字符串的截取,字符串首字母的索引为1

REPLACE(列|字符串,旧内容,新内容)

String

将指定字符串的指定部分字符替换

 

例1:SELECT UPPER(‘hellO’) FROM DUAL; //DUAL为虚拟表,供实验用

例2:SELECT LOWER(ENAME) ENAME FROM EMP;

例3:SELECT * FROM EMP WHERE ENAME=UPPER(‘&input’); //实现数据输入操作,&input为用户输入

例4:SELECT ENAME,SUBSTR(ENAME,-3) FROM EMP; //截取最后三位字符,Oracle独有

 

       |-    数值函数:      

函数

功能

ROUND(列|数值[,小数位数]

实现数值四舍五入,小数位数缺省值为0,负数则整数部分四舍五入

TRUNC(列|数值[,小数位数]

实现数值的截取(不四舍五入),小数位数缺省值为0,负数则整数部分截取

MOD(列|数值,列|数值)

求模(计算余数)

 

       |-    日期函数:

 

函数

返回值

功能

SYSDATE

当前日期

 

|-日期+数字=日期(若干天后的日期)

|-日期-数字=日期(若干天前的日期)

|-日期-日期=数字(天数)

SYSTIMESTAMP

时间戳

返回当前日期和时间

ADD_MONTHS(列|日期,月数)

日期

在指定日期上增加若干个月之后的日期

MONTHS_BETWEEN(列|日期,列|日期)

Int

返回两个日期之间所经历的月数

LAST_DAY(列|日期)

日期

返回指定日期所在月的最后一天

NEXT_DAY(列|日期)

日期

返回下一个指定的一周时间数对应的日期

 

例1:SELECT * FROM EMP WHERE HIREDATE=(LAST_DAY(HIREDATE)-2);

例2:SELECT NEXT_DAY(SYSDATE,'星期天') FROM DUAL; //下一个星期天日期

例3:

SELECT ENAME,HIREDATE,

TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12) YRAE,

TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,HIREDATE),12)) MONTH,

TRUNC(SYSDATE-ADD_MONTHS(HIREDATE,MONTHS_BETWEEN(SYSDATE,HIREDATE))) DAY

FROM EMP;  //HIREDATE与现在时间的年-月-日的差

 

       |-    转换函数:      

函数

返回值

功能

TO_CHAR(列|日期|数字,转换格式)

String

将日期或数值格式化为指定结构的字符串

TO_DATE(列|字符串,转换格式)

日期

按照指定的转换格式编写字符串后将其变为日期型数据

TO_NUMBER(列|字符串)

数字

将字符串转换为数值

              |-    转换格式

                     |-    日期:年(yyyy)、月(mm)、日(dd);

                     |-    时间:时(hh|hh24)、分(mi)、秒(ss);

                     |-    数字:任意数字(9)、本地货币符号(L)。

例1:SELECT TO_CHAR(SYSDATE,'YYYY/mm/dd hh24:mi:ss') FROM DUAL;

例2:

SELECT TO_CHAR(SYSDATE,'yyyy'),TO_CHAR(SYSDATE,'mm'),TO_CHAR(SYSDATE,'dd') FROM DUAL; //拆分日期的年月日

例3:SELECT *FROM EMP WHERE TO_CHAR(HIREDATE,'mm')='02'; //或者用=2

例4:SELECT TO_CHAR(123872181,'L999,999,999,999') NAME FROM DUAL;

例5:SELECT TO_DATE('1989-12-1','yyyy-mm-dd') FROM DUAL;

 

       |- 通用函数

函数

返回值

功能

NVL(列|NULL,默认值)

数字

如果传入内容是NULL,则使用默认数值处理,如果不是NULL则使用原始数据处理 //NULL参与的计算结果均为NULL

DECODE(列|字符串|数值,比较内容1,显示内容1比较内容2,显示内容2...[,默认显示内容]

数据类型

设置的内容会与每一个比较内容进行比较,如果内容相同,则会使用显示内容进行输出,如果都不相同,则使用最后的默认信息输出

 

例1:SELECT ENAME,SAL,COMM,(SAL+NVL(COMM,0))*12 INCOME FROM EMP;

例2:SELECT ENAME,JOB,DECODE(JOB,'CLERK','办事员','SALESMAN','销售员') 替换 FROM EMP; //没有匹配项且无默认显示内容的项,显示NULL

例3:SELECT ENAME,JOB,DECODE(JOB,'CLERK','办事员','SALESMAN','销售员',JOB) 替换 FROM EMP;

 

--------------------------------------------------------------------------------------------------------------

 

多表查询:       //性能很差!多表查询必须消除笛卡尔积

|-   SELECT [DISTINCT] *|列名称 [别名],列名称 [别名]... //③控制需要显示的列数据

FROM 表名称 [别名],表名称 [别名]        //①确定数据来源

[WHERE 过滤条件]        //②筛选满足条件的数据行

              [ORDER BY 字段 [ASC|DESC],字段 [ASC|DESC],      ...    ] //④排序

例1:SELECT * FROM EMP,DEPT WHERE EMP.DEPTNO=DEPT.DEPTNO; //笛卡尔积

例2:SELECT * FROM EMP e,DEPT d WHERE e.DEPTNO=d.DEPTNO; //使用表名

例3:SELECT e.ENAME,e.JOB,e.SAL,d.LOC

FROM EMP e,DEPT d

WHERE e.DEPTNO=d.DEPTNO;

例4:SELECT e.ENAME,e.JOB,e.SAL,,d.DNAME,d.LOC,g.GRADE

FROM EMP e,DEPT d,SALGRADE g

WHERE (e.DEPTNO=d.DEPTNO) AND (e.SAL BETWEEN g.LOSAL AND HISAL);

 

       |-    表的连接:

              |-    内连接(等值连接):所有满足条件的数据都会显示;

              |-    外连接(左外连接、右外连接、全外连接):控制左表与右表的数据是否全部显示;

                            //(+)Oracle独有语法

                     |-    左外连接:字段 = 字段(+);//让等号左的字段数据全部显示

                     |-    右外连接:字段(+) = 字段;//让等号右的字段数据全部显示

                            //SQL1999通用语法

                     |-    SELECT [DISTINCT] *| [别名]

FROM 表名称1

[CROSS JOIN表名称2]

       [NATURALJOIN表名称2]

       [JOIN表名称 ON(条件)|USING(字段)]//USING,指定关联字段;没有关联项,用ON设置关联条件

       [LEFT|RIGHT |FULL OUTER JOIN表名称2]

例1:SELECT e.ENAME,e.JOB,e.DEPTNO,d.DEPTNO,d.DNAME FROM EMP e,DEPT d WHERE e.DEPTNO=d.DEPTNO; //内连接

例2:SELECT e.ENAME,e.JOB,e.DEPTNO,d.DEPTNO,d.DNAME FROM EMP e,DEPT d WHERE e.DEPTNO=d.DEPTNO(+); //左连接,左字段表数据全部显示

例3:SELECT e.ENAME,e.JOB,e.DEPTNO,d.DEPTNO,d.DNAME FROM EMP e,DEPT d WHERE e.DEPTNO(+)=d.DEPTNO; //右链接,右字段表数据全部显示

例4:SELECT e.EMPNO,e.ENAME,e.JOB,e.MGR,d.ENAME FROM EMP e,EMP d WHERE e.MGR=d.EMPNO(+); //e的表格数据全部显示

例5:SELECT * FROM EMP CROSS JOIN DEPT; //交叉连接,产生笛卡尔积

例6:SELECT * FROM EMP NATURAL JOIN DEPT; //自动找到关联项,并内连接

例7:SELECT *FROM EMP JOIN DEPT USING(DEPTNO); //指定关联项进行内连接

例8:SELECT *FROM EMP e JOIN SALGRADE s ON (e.SAL BETWEEN s.LOSAL AND s.HISAL);

例9:SELECT * FROM EMP LEFT OUTER JOIN DEPT USING(DEPTNO); //左连接

 

数据集合操作:     //将多个处理的表合并显示,列一定要相同

|-    SELECT [DISTINCT] *| 列名称 [别名],列名称 [别名]...

FROM 表名称 [别名],表名称 [别名]

[WHERE 过滤条件]

                     [ORDERBY 字段 [ASC|DESC],字段 [ASC|DESC],      ...    ]

                     UNION|UNION ALL|INTERSECT|MINUS

              SELECT [DISTINCT] *|列名称 [别名],列名称 [别名]...

FROM 表名称 [别名],表名称 [别名]

[WHERE 过滤条件]

                     [ORDERBY 字段 [ASC|DESC],字段 [ASC|DESC],      ...    ]

                     ...

                     //UNION:如果遇见相同的内容,不会重复显示;

                     //UNION  ALL:如果遇见相同的内容,重复显示;

                     //INTERSECT:返回相同的数据部分,交集操作;

                     //MINUS:第一个查询结果减去后者的查询结果,差集操作

 

------------------------------------------------------------------------------------------------------------

 

基础统计函数:

       |-    统计个数:COUNT(*|[DISTINCT]字段)

       |-    最大、最小:MAX(字段)、MIN(字段)

       |-    合、平均值:SUN(字段)、AVG(字段)

 

       分组统计:

              |-   SELECT [DISTINCT] 分组字段 [别名]...|统计函数 //⑤

FROM 表名称 [别名],表名称 [别名//①

[WHERE 过滤条件]                   //②WHERE不允许使用分组函数

                            [GROUPBY 分组字段,分组字段,...] //③SELECT出现的字段(非统计函数),必须出现在GROUP BY中,GROUP BY的字段,只能多,不能少

                            [HAVING 分组后的过滤条件]   //④对分组后的数据筛选,即可以使用分组函数进行数据筛选

    [ORDER BY字段 [ASC|DESC], 字段 [ASC|DESC],      ...    ] //⑥

例1: SELECT JOB,COUNT(EMPNO),AVG(SAL) FROM EMP GROUP BY JOB;

例2:SELECT DEPTNO,COUNT(*),MAX(SAL),MIN(SAL) FROM EMP GROUP BY DEPTNO;

例3:SELECT d.DNAME,COUNT(e.ENAME),AVG(e.SAL)

FROM EMP e,DEPT d

WHERE d.DEPTNO=e.DEPTNO(+)

GROUP BY d.DNAME;

例4:SELECT d.DEPTNO,d.DNAME,d.LOC,COUNT(e.ENAME),

AVG(MONTHS_BETWEEN(SYSDATE,e.HIREDATE)/12)

      FROM EMP e,DEPT d

      WHERE e.DEPTNO(+)=d.DEPTNO

      GROUP BY d.DEPTNO,d.DNAME,d.LOC;

例5:SELECT JOB,AVG(SAL) FROM EMP GROUP BY JOB HAVING AVG(SAL)>2000;

显示非销售人员工作名称以及从事同一工作雇员的月工资的总和,并且要满足从事同一工作的雇员的月工资合计大于5000,输出结果按月工资的合计升序排序

SELECT JOB,SUM(SAL)

FROM EMP

WHERE JOB!='SALESMAN'

GROUP BY JOB

HAVING SUM(SAL)>5000

ORDER BY SUM(SAL);

统计公司所有领取佣金与不领取佣金的雇员人数、平均工资

SELECT '领取' title,COUNT(ENAME),AVG(SAL) FROM EMP

WHERE COMM IS NOT NULL

UNION

SELECT '不领取' title,COUNT(ENAME),AVG(SAL) FROM EMP

WHERE COMM IS NULL;

 

子查询://相对于多表查询,性能更高

       |-      SELECT [DISTINCT] 分组字段 [别名]...|统计函数(子查询)

FROM 表名称 [别名],表名称 [别名](子查询)

[WHERE 过滤条件(子查询)]

                     [GROUPBY 分组字段,分组字段,...]

     [HAVING分组后的过滤条件(子查询)]

     [ORDER BY字段 [ASC|DESC], 字段 [ASC|DESC],      ...    ]

WHERE子查询:子查询一般会返回单行单列、单行多列、多行单列;

HAVING子查询:子查询会返回单行单列,且使用统计函数;

FROM子查询:子查询返回多行多列(表结构),子查询的统计函数必须用别名;

SELECT子查询:返回单行单列,一般不使用。

              |-    ANY

                     =ANY(单列数据),相当于IN;

                     >ANY(单列数据),大于单列数据的最小值;

                     <ANY(单列数据),小于单列数据的最大值。

              |-    ALL

                     >ALL(单列数据),大于单列数据的最大值;

                     <ALL(单列数据),小于单列数据的最小值。

 

例1: SELECT *

FROM EMP

WHERE SAL<(

             SELECT AVG(SAL)

             FROM EMP

);    //子查询返回单行单列的平均工资数据

例2:SELECT *

FROM EMP

WHERE (JOB,SAL)=(

              SELECT JOB,SAL

          FROM EMP

              WHERE ENAME=’SCOTT’) AND (ENAME!=’SCOTT’); //返回单行多列

例3:SELECT *

FROM EMP

WHERE SAL NOT IN (

              SELECT SAL

              FROM EMP

              WHERE JOB=’MANAGER’); //返回多行单列

例4:SELECT *

FROM EMP

WHERE MGR NOT IN (

               SELECT MGR FROM EMP); //返回的多行单列包含NULL,NOT IN返回NULL

例5:SELECT *

FROM EMP

WHERE MGR =ANY (

              SELECT MGR FROM EMP);

例6:SELECT JOB,COUNT(ENAME),AVG(SAL)

FROM EMP

GROUP BY JOB

HAVING AVG(SAL)>(

             SELECT AVG(SAL) FROM EMP);

例7:SELECT e.EMPNO,e.ENAME,e.JOB,(

             SELECT d.DNAME

             FROM DEPT d

             WHERE e.DEPTNO=d.DEPTNO)

FROM EMP e;  //1+N次查询,不推荐使用

例8:SELECT d.DNAME,d.LOC,COUNT(e.ENAME)

FROM EMP e,DEPT d

WHERE e.DEPTNO(+)=d.DEPTNO

GROUP BY d.DNAME,d.LOC; //多表查询效率低

例9:SELECT d.DEPTNO,d.DNAME,d.LOC,e.COUNT

FROM DEPT d,(

              SELECT DEPTNO,COUNT(ENAME) COUNT

              FROM EMP

              GROUP BY DEPTNO) e

WHERE d.DEPTNO=e.DEPTNO(+); //相对于例8,子查询性能高!!!

 

综合:

列出薪金高于在部门30工作的所有员工的姓名和薪金、部门名称、部门人数。

SELECT e.ENAME,e.SAL,d.DNAME,c.COUNT

FROM EMP e,DEPT d,(

       SELECT DEPTNO,COUNT(ENAME) COUNT

       FROM EMP

       GROUP BY DEPTNO

) c

WHERE e.DEPTNO=d.DEPTNO AND d.DEPTNO=c.DEPTNO AND

e.SAL>ALL(

       SELECT SAL

       FROM EMP

       WHERE DEPTNO=30

);

列出与‘SCOTT’从事相同工作的所有员工及部门名称、部门人数和领导姓名。

SELECT e.ENAME,d.DNAME,c.COUNT,t.ENAME

FROM EMP e,DEPT d,(

       SELECT DEPTNO,COUNT(ENAME) COUNT

       FROM EMP

       GROUP BY DEPTNO

) c,EMP t

WHERE e.JOB=(

       SELECT JOB FROM EMP WHERE ENAME='SCOTT'

) AND e.DEPTNO=d.DEPTNO AND d.DEPTNO=c.DEPTNO

AND e.MGR=t.EMPNO AND e.ENAME!='SCOTT';

列出薪金比’SMITH’或’ALLEN’多的所有员工的编号、姓名、部门名称、领导姓名,部门人数、平均工资、最高最低工资。

SELECT e.EMPNO,e.ENAME,d.DNAME,e2.ENAME,c.COUNT,c.AVG,c.MAX,c.MIN

FROM EMP e,DEPT d,(

       SELECT EMPNO,ENAME

       FROM EMP

) e2,(

       SELECT DEPTNO,COUNT(ENAME) COUNT,AVG(SAL) AVG,MAX(SAL) MAX,MIN(SAL) MIN

       FROM EMP

       GROUP BY DEPTNO

) c

WHERE e.SAL>ANY(

       SELECT SAL

       FROM EMP

       WHERE ENAME IN ('SMITH','ALLEN')

) AND e.DEPTNO=d.DEPTNO

AND d.DEPTNO=c.DEPTNO

AND e.MGR=e2.EMPNO(+)

AND e.ENAME NOT IN ('SMITH','ALLEN');

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值