Oracle:数据查询语言-DQL-select

前端之家收集整理的这篇文章主要介绍了Oracle:数据查询语言-DQL-select前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

SELECT语句功能

投影操作:结果集是源表中的部分列。

选择操作:结果集是源表中的部分行。

连接操作:将两张表里的行按某种条件组合成一条长长的行放入结果集。

最基本的用法:SELECT ……FROM……

SELECT子句

用于指定字段名,多个字段名用逗号隔开,*代表所有列。

SELECT后面可以跟列,字符,表达式,DISTINCT关键字(去掉重复行),函数,常量,组标识。完成对数据的处理。

FROM子句

用于指定表名。

例如:SELECT DISTINCT NAME FROM TEST;

WHERE子句

根据条件过滤出需要处理的数据,对行过滤。后面跟条件表达式(列名,常量,比较运算符,文字值,不能跟列别名),可以用AND,OR连接多个条件表达式。

语法顺序:SELECT……FROM……WHERE……

例如:SELECT NAME FROM TEST WHERE ID = 10001;

ORDER BY子句

SELECT语句的最后一个子句,也是最后执行的子句,功能是改变记录的输出顺序,排序。

ASC(缺省/默认) 升序,DESC降序。

ORDER BY后面可以跟列名,表达式,列别名,列在结果集中的位置值。

ORDER BY 后面可以跟多列,用逗号隔开。

NULL值在ORDER BY 子句中排序的顺序是:降序排在最上,升序排在最下。

语法顺序:SELECT ——> FROM ——> WHERE ——> ORDER BY

执行顺序:FROM ——> WHERE ——> SELECT ——> ORDER BY

例如:SELECT * FROM TEST ORDER BY NAME DESC;

GROUP BY子句

功能是根据指定的列对行进行分组

语法顺序:SELECT……FROM……WHERE……GROUP BY……ORDER BY……

执行顺序:FROM……WHERE……GROUP BY……SELECT……ORDER BY……

例如:SELECT NAME FROM SERVICE GROUP BY NAME;

注意:

在SELECT语句中,如果没有GROUP BY子句,若在SELECT子句中有一个组函数,那么其他都必须是组函数,否则会报错。

在SELECT语句中,如果有GROUP BY子句,SELECT子句中可跟组函数,或GROUP BY后面的表达式、组标识,其他会报错。

GROUP BY中包含多列的情况,用逗号隔开,分组的粒度更细,每组的记录少了,但组多了。

行级信息和组级信息不可以同时显示出来。

HAVING 子句

功能是对组过滤,后面接条件表达式。

语法顺序:SELECT……FROM……WHERE……GROUP BY……HAVING……ORDER BY……

执行顺序:FROM……WHERE……GROUP BY……HAVING……SELECT……ORDER BY……

WHERE和HAVING 的区别:

1、WHERE过滤的是行(记录)

2、HAVING过滤的是分组(组标识,每组数据的聚合结果)

3、WHERE后面可以跟任意列名,单行函数,不能跟组函数

4、HAVING后面只能跟组函数、组标识、GROUP BY后面的表达式

5、WHERE子句执行在前,HAVING子句执行在后

6、WHERE子句和HAVING子句都不允许有列别名

设置结果集每页显示的记录数

SET PAGESIZE 记录数;

设置显示结果集时每行的长度

SET LINESIZE 长度;

设置当前会话的日期格式

ALTER SESSION SET NLS_DATE_FORMAT='格式';

例如:

ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';

把SELECT出来的结果导到一个文本文件

SPOOL 路径\文件名.TXT;

SELECT * FROM 表名;

SPOOL OFF;

新建两个表,并插入一些数据:
CREATE TABLE CUSTOMER_TEST(ID VARCHAR2(48),CODE VARCHAR2(48),NAME VARCHAR2(58),TEL VARCHAR2(16),ADDRESS VARCHAR2(80),CREATETIME TIMESTAMP DEFAULT SYSDATE,REMARK VARCHAR2(80));

INSERT INTO CUSTOMER_TEST
  (ID,CODE,NAME,TEL,ADDRESS,CREATETIME,REMARK)
VALUES
  ('C000000000000000000001','C000000000000000000001','张三','15044447777','广东深圳宝安XXXX',TO_DATE('2015-01-01 09:30:29','yyyy-mm-dd hh24:mi:ss'),'ABCDEFG');

INSERT INTO CUSTOMER_TEST
  (ID,REMARK)
VALUES
  ('C000000000000000000002','C000000000000000000002','李四','15122336548',TO_DATE('2015-01-01 11:30:29',REMARK)
VALUES
  ('C000000000000000000003','C000000000000000000003','王五','13456892112',TO_DATE('2016-02-01 10:30:29',REMARK)
VALUES
  ('C000000000000000000004','C000000000000000000004','赵六','17766522233',TO_DATE('2016-02-10 09:30:29',REMARK)
VALUES
  ('C000000000000000000005','C000000000000000000005','刘七','13154546666','广东深圳宝安XXXXX',TO_DATE('2016-03-01 09:30:29','ABCDEFG');

COMMIT;

CREATE TABLE ORDER_TEST(ID VARCHAR2(48),CUSTOMERID VARCHAR2(48),COMMODITYIDS VARCHAR2(800),ORDERNUMBER VARCHAR2(48),ORDERTIME       TIMESTAMP DEFAULT SYSDATE,REMARK VARCHAR2(80),DELIVERYADDRESS VARCHAR2(80));

INSERT INTO ORDER_TEST
  (ID,CUSTOMERID,COMMODITYIDS,ORDERNUMBER,ORDERTIME,REMARK,DELIVERYADDRESS)
VALUES
  ('O000000000000000000001','C001,C002,C003,C004,C005','O000000000000000000001',TO_DATE('2016-01-01 17:09:50','不要错了','广东广州白云XXXXX');

INSERT INTO ORDER_TEST
  (ID,DELIVERYADDRESS)
VALUES
  ('O000000000000000000002','O000000000000000000002',TO_DATE('2016-03-10 17:09:50','广东广州白云XXXXX');
   
INSERT INTO ORDER_TEST
  (ID,DELIVERYADDRESS)
VALUES
  ('O000000000000000000003','O000000000000000000003',TO_DATE('2016-03-11 17:09:50','广东东莞虎门XXXXX');
   
INSERT INTO ORDER_TEST
  (ID,DELIVERYADDRESS)
VALUES
  ('O000000000000000000004','O000000000000000000004','广东东莞后街XXXXX');   
   
INSERT INTO ORDER_TEST
  (ID,DELIVERYADDRESS)
VALUES
  ('O000000000000000000005','O000000000000000000005',TO_DATE('2016-02-11 17:09:50','广东东莞后街XXXXX');   
   
COMMIT;   

非关联子查询查询过程中内表不需要引用主表中的列

先执行子查询,子查询的结果作为条件,再执行主查询。子查询只执行一次。

查询在2016年2月有订单的客户:

sql> SELECT C.NAME

2 FROM CUSTOMER_TEST C

3 WHERE C.ID IN

4 (SELECT O.CUSTOMERID

5 FROM ORDER_TEST O

6 WHERE O.ORDERTIME >=

7 TO_DATE('2016-02-01 00:00:00','yyyy-mm-dd hh24:mi:ss')

8 AND O.ORDERTIME <=

9 TO_DATE('2016-02-29 23:59:59','yyyy-mm-dd hh24:mi:ss'));

NAME

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

赵六

关联子查询在子查询中引用主表中的列

3 WHERE EXISTS (SELECT 1

4 FROM ORDER_TEST O

5 WHERE O.ORDERTIME >=

6 TO_DATE('2016-02-01 00:00:00',courier; font-size: 14px;"> 7 AND O.ORDERTIME <=

8 TO_DATE('2016-02-29 23:59:59',courier; font-size: 14px;"> 9 AND C.ID = O.CUSTOMERID);

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

多列子查询查询的where条件中可以用多个列进行过滤(多列条件表达式)

查询收货地址相同,且购买商品相同的客户:

3 WHERE C.ID IN (SELECT O.CUSTOMERID

4 FROM ORDER_TEST O

5 WHERE (O.COMMODITYIDS,O.DELIVERYADDRESS) IN

6 (SELECT O.COMMODITYIDS,O.DELIVERYADDRESS

7 FROM ORDER_TEST O

8 GROUP BY O.COMMODITYIDS,courier; font-size: 14px;"> 9 HAVING COUNT(DISTINCT O.CUSTOMERID) > 1));

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

王五

EXISTS:用于检查子查询是否至少会返回一行数据,实际上并不在乎子查询返回任何具体数据,而是在乎是否有值返回,有则是True否则为False。

3 WHERE EXISTS (SELECT 1

9 AND C.ID = O.CUSTOMERID);

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

NOT EXISTS:与exists相反。

查询在2016年2月没有订单的客户:

3 WHERE NOT EXISTS

4 (SELECT 1

10 AND C.ID = O.CUSTOMERID);

张三

李四

刘七

IN与EXISTS的比较

如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用IN。

反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用EXISTS。

其实我们区分IN和EXISTS主要是造成了驱动顺序的改变(这是性能变化的关键),如果是EXISTS,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了。

表连接查询

交叉连接(CROSS JOIN)

假设TABLE1中有M条记录,TABLE2中有N条记录,那么交叉连接的结果集为M*N条记录。该连接产生的结果集称为笛卡尔集。

sql> SELECT COUNT(1) FROM CUSTOMER_TEST C,ORDER_TEST O;

COUNT(1)

----------

25

sql> SELECT COUNT(1) FROM CUSTOMER_TEST C CROSS JOIN ORDER_TEST O;

25

内连接(INNER JOIN)

任何一张表里的记录一定要在另一张表中找到匹配的记录,否则不能出现在结果集中。

3 INNER JOIN ORDER_TEST O

4 ON C.ID = O.CUSTOMERID

5 WHERE O.ORDERTIME >=

6 TO_DATE('2016-02-01 00:00:00',courier; font-size: 14px;"> 7 AND O.ORDERTIME <=

8 TO_DATE('2016-02-29 23:59:59','yyyy-mm-dd hh24:mi:ss');

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

2 FROM CUSTOMER_TEST C,ORDER_TEST O

3 WHERE C.ID = O.CUSTOMERID

4 AND O.ORDERTIME >=

5 TO_DATE('2016-02-01 00:00:00',courier; font-size: 14px;"> 6 AND O.ORDERTIME <=

7 TO_DATE('2016-02-29 23:59:59',courier; font-size: 14px;">--------------

外连接(LEFT JOIN,RIGHT JOIN,FULL JOIN)

左连接LEFT OUTER JOIN

查询每个用户单号:

sql> SELECT C.NAME,O.ORDERNUMBER

3 LEFT JOIN ORDER_TEST O

5 ORDER BY C.NAME;

NAME ORDERNUMBER

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

刘七

张三 O000000000000000000001

张三 O000000000000000000002

李四 O000000000000000000003

王五 O000000000000000000004

赵六 O000000000000000000005

RIGHT OUTER JOIN

sql> SELECT O.ORDERNUMBER,C.NAME

2 FROM ORDER_TEST O

3 RIGHT JOIN CUSTOMER_TEST C

ORDERNUMBER NAME

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

刘七

O000000000000000000001 张三

O000000000000000000002 张三

O000000000000000000003 李四

O000000000000000000004 王五

O000000000000000000005 赵六

FULL OUTER JOIN

FROM后面跟子查询

在表连接过程中,有时候需要先对其中一个表先进行数据过滤在连接,这就是在FROM后面跟子查询

这种情况会先执行子查询,将子查询的结果集作为一个表与另一个表进行连接。

查询在2016年2月有订单的客户及其订单号:

2 FROM (SELECT CUSTOMERID,ORDERNUMBER

3 FROM ORDER_TEST

4 WHERE ORDERTIME >=

5 TO_DATE('2016-02-01 00:00:00',courier; font-size: 14px; color: #0000ff;"> 6 AND ORDERTIME <=

7 TO_DATE('2016-02-29 23:59:59','yyyy-mm-dd hh24:mi:ss')) O

8 JOIN CUSTOMER_TEST C

9 ON C.ID = O.CUSTOMERID;

NAME ORDERNUMBER

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

赵六 O000000000000000000005

结果集运算

UNION/UNION ALL:结果集为两个查询结果的并集。UNION会进行对数据进行去重操作;UNION ALL直接将两个结果集合并在一起,不会去重。

INTERSECT:结果集为两个查询结果的交集。

MINUS:结果集属于第一个查询结果,但不属于第二个查询结果。即为第一个查询结果集减去与第二个查询结果集的交集。

集合运算中,要求两个SELECT语句中列的个数、数据类型是一样的(即同构的)。

分页查询

Oracle的分页利用ROWNUM

ROWNUM是一个伪列,对查询返回的行进行编号即行号,从1开始递增。ORACLE的ROWNUM值是在获得每行之后才赋予的。

sql> SELECT ROWNUM,C.NAME FROM CUSTOMER_TEST C;

ROWNUM NAME

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

1 张三

2 李四

3 王五

4 赵六

5 刘七

ROWNUM的产生:

假如有一条查询语句为SELECT XX,YY FROM TABLE WHERE ZZ > 20 AND ROWNUM < 10。

执行FROM TABLE,从中取出第一条记录,系统给这条记录进行ROWNUM编号为1;

执行WHERE子句,判断记录是否符合条件表达式,符合则留下,不符合就丢弃;

从TABLE中取出第二条记录,这条记录的ROWNUM编号,为前一条符合条件被留下的记录的ROWNUM + 1;

重复前面的步骤,直到不符合ROWNUM < 10为止。

例如:当前页码pageIndex为3,页容量pageSize为2,查询当前页的数据:

sql> SELECT ROW_.*

2 FROM (SELECT ROWNUM RN,C.NAME FROM CUSTOMER_TEST C WHERE ROWNUM <= 3 * 2) ROW_

3 WHERE ROW_.RN > (3 - 1) * 2;

RN NAME

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

5 刘七

分页查询开始的startRowNum = (pageIndex - 1) * pageSize; 结束endRowNum = pageIndex * pageSize + 1。startRowNum与endRowNum都不包含在当前页中。

原文链接:https://www.f2er.com/oracle/211667.html

猜你在找的Oracle相关文章