欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OCP SQL 例子-2

程序员文章站 2022-03-25 20:27:01
...
--external table
--查询时从外部文件中读取到定义好的表中,但Oracle并不保存数据,是对sqlldr工具的一个补充
--下面的例子,测试用 external table读取oracle日志文件。


-- 创建Oracle目录,指向Oracle的日志文件位置

CREATE DIRECTORY ORCL_LOG as 'F:\oracle\product\10.2.0\db_1\admin\orcl\bdump';
--创建外部表

CREATE TABLE ALERT_LOG(
LOG_TEXT VARCHAR2(4000)
)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY ORCL_LOG
ACCESS PARAMETERS
(
 RECORDS DELIMITED BY NEWLINE--每一行是一条记录
 NOBADFILE
 NODISCARDFILE
 NOLOGFILE
 )
 LOCATION('ALERT_ORCL.LOG')
 )
 REJECT LIMIT UNLIMITED;
--查询外部表

SELECT * FROM ALERT_LOG WHERE ROWNUM <= 10;

LOG_TEXT
-----------------------------------------------------------------------

Dump file f:\oracle\product\10.2.0\db_1/admin/orcl/bdump\alert_orcl.log
Sun Oct 21 09:39:32 2012
ORACLE V10.2.0.1.0 - Production vsnsta=0
vsnsql=14 vsnxtr=3
Windows NT Version V6.1 Service Pack 1
CPU                 : 4 - type 586
Process Affinity    : 0x00000000
Memory (Avail/Total): Ph:285M/1991M
Sun Oct 21 09:39:32 2012
Starting ORACLE instance (normal)
------------------------------------------------------------------------------------------------------------------------------------
--MERGE的使用
--先来看下Merge的语法
/*
MERGE INTO TABLE
USING TABLE|SUBQUERY
ON CONDITION
WHEN MATCHED THEN UPDATE SET COL = EXPRESSION | DEFAULT
     WHERE_CLAUSE
     DELETE WHERE_CLAUSE
WHEN NOT MATCHED THEN INSERT(COL,COL2)
     VALUES(EXPR1,EXPR2,|DEFAULT)
     WHERE_CLAUSE
WHERE CONDITION;*/
DROP TABLE TAB1;
DROP TABLE TAB2;

CREATE TABLE TAB1(ID INT, NAME VARCHAR2(10),STATUS VARCHAR2(10));
CREATE TABLE TAB2(ID INT, NAME VARCHAR2(10));

INSERT INTO TAB1 VALUES(1,'ANKER','N');
INSERT INTO TAB1 VALUES(2,'MIN','U');
INSERT INTO TAB1 VALUES(3,'MING','D');
INSERT INTO TAB1 VALUES(4,'XIAO','U');
INSERT INTO TAB2 VALUES(2,'A');
INSERT INTO TAB2 VALUES(3,'MING');
INSERT INTO TAB2 VALUES(4,'B');
COMMIT;

SELECT * FROM TAB1;

       ID NAME       STATUS
--------- ---------- ----------
        1 ANKER      N
        2 MIN        U
        3 MING       D
        4 XIAO       U
SELECT * FROM TAB2;

        ID NAME
---------- ----------
         2 A
         3 MING
         4 B

MERGE INTO TAB2         
USING TAB1 ON (TAB2.ID = TAB1.ID)
WHEN MATCHED THEN UPDATE SET NAME = TAB1.NAME 
  DELETE WHERE (TAB1.STATUS = 'D')
WHEN NOT MATCHED THEN INSERT(ID,NAME) VALUES(TAB1.ID,TAB1.NAME)
  WHERE 1=1;
  
SELECT * FROM TAB2;--查看合并之后的结果

        ID NAME
---------- ----------
         2 A
         3 MING
         4 B

------------------------------------------------------------------------------------------------------------------------------------------
--connect by 层次嵌套查询
DROP TABLE TT;

CREATE TABLE TT
(
ID INT,
PARENT_ID INT,
NAME VARCHAR2(10)
);

INSERT INTO TT VALUES(1,NULL,'CEO');
INSERT INTO TT VALUES(2,1,'VP');
INSERT INTO TT VALUES(3,1,'SVP');
INSERT INTO TT VALUES(4,1,'CFO');
INSERT INTO TT VALUES(5,2,'DIRECTOR 1');
INSERT INTO TT VALUES(6,2,'DIRECTOR 2');
INSERT INTO TT VALUES(7,3,'DIRECTOR 3');
INSERT INTO TT VALUES(8,3,'DIRECTOR 4');
INSERT INTO TT VALUES(9,6,'MANAGER 1');
COMMIT;

SELECT * FROM TT;

        ID  PARENT_ID NAME
---------- ---------- ----------
         1            CEO
         2          1 VP
         3          1 SVP
         4          1 CFO
         5          2 DIRECTOR 1
         6          2 DIRECTOR 2
         7          3 DIRECTOR 3
         8          3 DIRECTOR 4
         9          6 MANAGER 1

SELECT * FROM TT START WITH ID = 2 CONNECT BY PRIOR ID = PARENT_ID;

        ID  PARENT_ID NAME
---------- ---------- ----------
         2          1 VP
         5          2 DIRECTOR 1
         6          2 DIRECTOR 2
         9          6 MANAGER 1
         
--START WITH 标示开始的记录 
-- CONNECT BY 表示与当前记录关联的字段关系
--PIROR ID = PARENT_ID,我是这样理解的,当前条(也是上一条)的ID等于下一条的PARENT ID。



SELECT * FROM TT START WITH ID = 2 CONNECT BY ID = PRIOR PARENT_ID;
--连接条件是当前条(也是上一条)的PARENT_ID等于下一条的ID


        ID  PARENT_ID NAME
---------- ---------- ----------
         2          1 VP
         1            CEO

--来学习学习层次查询的一些伪列使用

SELECT 
 LEVEL, --树状结构的层次
 LPAD(' ', 2 * LEVEL) || NAME, 
 SYS_CONNECT_BY_PATH(NAME, '/'),--层次结构显示
 CONNECT_BY_ISLEAF,--是否是叶子节点,即下面没有子节点
 CONNECT_BY_ROOT(NAME)--显示树状结构的ROOT
  FROM TT
 START WITH ID = 2
CONNECT BY PRIOR ID = PARENT_ID
ORDER SIBLINGS BY ID DESC;--指定子节点相同时,排序的条件
------------------------------------------------------------------------------------------------------------------------------------
--NATRUAL JOIN
CREATE TABLE TT (ID INT,CODE VARCHAR2(10));
CREATE TABLE TT1 (CODE VARCHAR2(10),NAME VARCHAR2(10));
INSERT INTO TT VALUES(1,'A');
INSERT INTO TT VALUES(2,'B');
INSERT INTO TT VALUES(3,'C');
INSERT INTO TT1 VALUES('A','JSP');
INSERT INTO TT1 VALUES('B','JAVA');

SELECT * FROM TT;

       ID CODE
--------- ----------
        1 A
        2 B
        3 C
SELECT * FROM TT1;
CODE       NAME
---------- ----------
A          JSP
B          JAVA
D          ORACLE

SELECT TT.ID, CODE, TT1.NAME FROM TT NATURAL JOIN TT1;

        ID CODE       NAME
---------- ---------- ----------
         1 A          JSP
         2 B          JAVA

--NATRUAL JOIN 会自动根据两个表相同的字段进行连接。不需要指定ON条件
--需要注意一点对于连接的字段,不能使用表限定,如下:

admin@ORCL> SELECT TT.ID, TT.CODE, TT1.NAME FROM TT NATURAL JOIN TT1;
SELECT TT.ID, TT.CODE, TT1.NAME FROM TT NATURAL JOIN TT1
              *
第 1 行出现错误:
ORA-25155: NATURAL 联接中使用的列不能有限定词
--------------------------------------------------------------------------------------------------------------------------------------
--USING的使用
--USING 使用在INNER JOIN 和 OUTER JOIN 中(包括FULL OUTER JOIN)。
--需要注意一点,连接的表列不能有限定词
SELECT TT.ID, CODE, TT1.NAME FROM TT INNER JOIN TT1 USING (CODE);

        ID CODE       NAME
---------- ---------- ----------
         1 A          JSP
         2 B          JAVA
         
SELECT TT.ID, CODE, TT1.NAME FROM TT LEFT JOIN TT1 USING (CODE);

        ID CODE       NAME
---------- ---------- ----------
         1 A          JSP
         2 B          JAVA
         3 C
-----------------------------------------------------------------------------------------------------------------------------------
--ANY SOME ALL
SELECT CODE FROM TT;
        ID CODE
---------- ----------
         1 A
         2 B
         3 C

SELECT CODE FROM TT1;
CODE       NAME
---------- ----------
A          JSP
B          JAVA
D          ORACLE

--ANY的用法
SELECT * FROM TT WHERE CODE > ANY(SELECT CODE FROM TT1);
       ID CODE
--------- ----------
        3 C
        2 B
--从结果可以看出,ANY的意思是任何一个。上面的语句意思是显示TT表中大于TT1表中最小的CODE值。
--也就等于以下SQL

SELECT * FROM TT WHERE CODE > (SELECT MIN(CODE) FROM TT1);


--来看SOME,实际上是与ANY是一样的。

SELECT * FROM TT WHERE CODE > SOME(SELECT CODE FROM TT1);

        ID CODE
---------- ----------
         3 C
         2 B
--来看看ALL
SELECT * FROM TT1 WHERE CODE > ALL (SELECT CODE FROM TT);

CODE       NAME
---------- ----------
D          ORACLE

--显示的是TT1表中,比TT表中所有的CODE都大的记录。上面的SQL也等价于

SELECT * FROM TT1 WHERE CODE > (SELECT MAX(CODE) FROM TT);

------------------------------------------------------------------------------------------------------------------------------------
--WITH AS的使用
--WITH AS相当于把一个SQL的中间结果保存到一个临时表中,供多次使用,用户提高SQL的可读性。
--此临时表生命周期只是查询的SQL内部
WITH TAB_TT AS
 (SELECT * FROM TT)
SELECT * FROM TAB_TT;
        ID CODE

---------- ----------         
1 		A         
2 		B        
3 		C
--listagg的使用
WITH TEMP AS(
  SELECT 500 POPULATION, 'CHINA' NATION ,'GUANGZHOU' CITY FROM DUAL UNION ALL
  SELECT 1500 POPULATION, 'CHINA' NATION ,'SHANGHAI' CITY FROM DUAL UNION ALL
  SELECT 500 POPULATION, 'CHINA' NATION ,'BEIJING' CITY FROM DUAL UNION ALL
  SELECT 1000 POPULATION, 'USA' NATION ,'NEW YORK' CITY FROM DUAL UNION ALL
  SELECT 500 POPULATION, 'USA' NATION ,'BOSTOM' CITY FROM DUAL UNION ALL
  SELECT 500 POPULATION, 'JAPAN' NATION ,'TOKYO' CITY FROM DUAL
)
SELECT POPULATION,
      NATION,
      CITY,
      LISTAGG(CITY,',') WITHIN GROUP (ORDER BY CITY DESC) OVER (PARTITION BY NATION) RANK
      FROM TEMP;
POPULATION NATIO CITY      RANK
---------- ----- --------- ------------------------------
      1500 CHINA SHANGHAI  SHANGHAI,GUANGZHOU,BEIJING
       500 CHINA GUANGZHOU SHANGHAI,GUANGZHOU,BEIJING
       500 CHINA BEIJING   SHANGHAI,GUANGZHOU,BEIJING
       500 JAPAN TOKYO     TOKYO
      1000 USA   NEW YORK  NEW YORK,BOSTOM
       500 USA   BOSTOM    NEW YORK,BOST