oracle SQL学习

--第一单元 select 语句

oracle开发的金科玉律

--1 oracle底层的标准产品只能查询,不能更新、删除、增加,因为背后的各个表关系错综复杂

-- 2 熟悉oracle 数据库官方文档,尽量使用oracle数据库的方法解决复杂问题


--数据库设计的三原则

--P:分布性

--A:高可用性

--C:一致性


--权限分配原则:最小权限原则

--数据库连接在中间键开发中不推荐使用


--查询类型

--列查询
SELECT employee_id  FROM   employees;
--行查询
SELECT * FROM   employees;
--多表连接查询
SELECT emp.* , dep.* FROM   employees   emp  ,departments dep

WHERE  emp.department_id = dep.department_id;

--设计查询语句时注意

--1逻辑清晰、易于理解

--2提高效率、优化查询


--设计查询思路:在哪些表(from)  以什么条件(where) 查询什么字段(select)


--oracle 关系型数据库的多个表呈现 星型结构


--主表的链接作用巨大

select table1.column1--主表(包含众多外表的主键)

,     table2.column2--次表

from  table1,table2

;

--oracle对类型转换的处理:

--oracle优化器:CBO(基于开销的优化)、RBO(基于关系的优化),默认采用CBO

--oracle 优化器会进行数据采集,统计分析,会自动修改连接的顺序或匹配的顺序,在进行数据类型的转换兼容时,顺序特别关键。

--eg:“123”(number)--“123”(varchar2):ok

--“123”(varchar2)--“123”(number):maybe ok,or not

 

--*

--使用*的弊端:1数据冗余 2不易于扩展(所需要的列不同:次序、数量、)


--别名的使用问题:

--建议表尽量使用别名,别名的好处:简短、表意,别名双引号

 select last_name as name  --标准化写法,对于用户理解产品有好处

,commission_pct comm      --oracle优化写法的,对于效率有帮助,项目的开发推荐使用,简洁,高效

from employees

;


--distinct
SELECT DISTINCT emp.* FROM   employees emp;
--备注:distinct 作用:删除表中重复部分,根据distinct后面连接内容进行比较,如distinct employee_id 
--则根据employee_id判断是否重复,如果为distinct employee_id ,dempartment_id 则根据employee_id 与dempartment_id
--综合起来进行比较,即employee_id ,dempartment_id需要完全相同才是为重复,才会去除
--慎用distinct,distinct由于会将该记录与全表其余记录逐个进行比较,共有n*n次,会有很大的性能问题

--Distinct会将所有表先进行排序,有可能导致内存不够,会在磁盘创建临时表空间,使得效率急剧降低。使用Distinct的情况:查询的表的行很少

--内存(SGA)—效率高,速度高:缓存区、排序区

--磁盘—效率低,速度低:DBF-分配内存、TEMP(临时表空间)


--null
SELECT emp.*
FROM   employees emp
WHERE  emp.department_id IS NULL;
--null 表示不可用、未赋值、不知道、不适用,既不是0也不是空
--和null进行数字运算,结果为空,和null进行逻辑运算,得根据null不知道的本质,推导出结果
--is null 是数据库提供的函数,用于判断是否为null

--eg: a.x=b.y or(a.x is null and b.y is null)


--别名
SELECT emp.employee_id AS "EID"
       ,emp.last_name   ename
       ,emp.job_id      "job"
       ,emp.job_id      AS job
FROM   employees emp;
--备注: 带as 、不带as 都能作为别名适用,“”表示别名大小写敏感,大小写固定,推荐不带as ,简洁

--字符串连接操作符||
SELECT last_name || ' works  in ' || department_id AS "Personal info"
FROM   employees;
--备注:字符串连接操作符将各个属性串联起来作为完整语句适用



--第二单元 条件限制和排序

--条件类型:关联条件、过滤条件


--比较操作符 =、>、>=、<、<=、<>、!=、between...and..、in、like、is null


--between ..and ..
SELECT *
FROM   employees
WHERE  salary BETWEEN 10000 AND 20000
AND    NOT department_id IS NULL;
SELECT *
FROM   employees
WHERE  salary BETWEEN 10000 AND 20000
AND    department_id IS NOT NULL;
--备注:数据库语句支持非运算,between...and 与 < ...and >... 或 >...and <...的查询效果与查询效率是一样的
--oracle会自带优化器,优化器会根据SQL语句形成特定的查询路径,查询路径不同,会有效率的不同,但高版本的oracle已经
--对一些具有相同功能的SQL语句进行优化


--IN
SELECT employee_id
      ,manager_id
FROM   employees
WHERE  manager_id IN (100
                     ,101
                     ,102);
SELECT employee_id
      ,manager_id
FROM   employees
WHERE  manager_id NOT IN (100
                         ,101
                         ,102
                         ,103
                         ,104);
--备注:IN 作用:有限范围的匹配,IN的原理过程:一般会将每条记录,与in中的数据逐个进行比较配对,查询的次数为N*M
--(M即为in范围的数据个数),由此可知in中的数据不能过多,一旦过多,会严重影响性能,oracle也会自动提示


--模糊匹配 like % 代表0或多个字符 _代表一个单个字符
SELECT employee_id
      ,last_name
FROM   employees
WHERE  last_name LIKE 'K%';
--备注:有些特殊字符,可以用转义符来表示,如‘\%’


--逻辑操作符 and or not
SELECT emp1.employee_id
      ,emp1.salary
FROM   employees emp1
      ,employees emp2
WHERE  emp1.salary = emp2.salary
AND    emp1.employee_id != emp2.employee_id;


--order by
SELECT employee_id
      ,salary
FROM   employees
ORDER  BY salary;
SELECT employee_id
      ,salary
FROM   employees
ORDER  BY salary ASC;
SELECT employee_id
      ,salary
FROM   employees
ORDER  BY salary DESC;
SELECT employee_id
      ,salary
FROM   employees
ORDER  BY salary DESC
         ,employee_id;

--order by 后面若没有指名,默认升序排序

--伪表 dual 只有一行一列,供开发人员查询系统时间等使用


--第三单元
--函数类型:单行函数、多行函数
--字符函数、数值函数、日期函数、转换函数、通用函数


--大小写转换函数
SELECT employee_id
      ,lower(first_name)
      ,upper(last_name)
      ,initcap(email)
FROM   employees;
--备注:LOWER(first_name) 转换为小写 ;UPPER(last_name)转换为大写,INITCAP(email),单词首字母大写


--字符串操作函数
SELECT concat('Hello'
             ,'World')
      ,substr('ABCDEFGHIJK'
             ,1
             ,5)
      ,length('ABCDEFGHIJK')
      ,instr('ABCDEFGHIJK'
            ,'E')
      ,lpad('ABCDEF'
           ,10
           ,'*')
      ,rpad('ABCDEF'
           ,10
           ,'*')
      ,TRIM('A' FROM 'ABCDEFGHIJK')
      ,TRIM('K' FROM 'ABCDEFGHIJK')
      ,TRIM('E' FROM 'ABCDEFGHIJK')
      ,TRIM(' ABCDEFGHIJK ')
      ,TRIM('ABCDE FGHIJK')
FROM   dual;
--CONCAT('Hello','World') 拼接函数,将两组字符串组合在一起
--SUBSTR('ABCDEFGHIJK',1,5),取指定字符串中从第二个参数之后,连续第三个参数
--LENGTH('ABCDEFGHIJK'),取指定字符串的长度
--INSTR('ABCDEFGHIJK','E'),取第二个参数在第一个参数的位置
--LPAD('ABCDEF',10,'*'),第二个参数说明长度,如果第一个参数长度不够,则向右靠齐,不足的地方补齐
--RPAD ('ABCDEF',10,'*'),第二个参数说明长度,如果第一个参数长度不够,则向左靠齐,不足的地方补齐
--TRIM('A' FROM'ABCDEFGHIJK'),第一个参数需在第二个参数的左右最外边,才能截取,否则没有效果
--TRIM('K' FROM'ABCDEFGHIJK')
--TRIM('E' FROM'ABCDEFGHIJK')
--TRIM (' ABCDEFGHIJK '),会自动将参数最外边的空格截取掉
--TRIM ('ABCDE FGHIJK')


--数字操作函数
SELECT round(123.456
            ,2)
      ,round(123.456
            ,-2)
      ,trunc(123.456
            ,2)
      ,MOD(1600
          ,300)
FROM   dual;
--ROUND(123.456,2) 依据四舍五入,2,小数点后2位之后的数进行取舍
--ROUND(123.456,-2)依据四舍五入,2,小数点前2位之前的数进行取舍
--TRUNC (123.456,2)直接截断小数点后2位自后
--MOD(1600,300) 取余
--dual:oracle提供的伪列,帮助用户了解系统属性,没有实际意义,用户可以借助daul进行预算


--日期函数
SELECT months_between(to_date('1990-05-08'
                             ,'yyyy-mm-dd')
                     ,to_date('1991-05-08'
                             ,'yyyy-mm-dd'))
      ,add_months(to_date('1990-01-01'
                         ,'yyyy-mm-dd')
                 ,5)
      ,next_day(to_date('1990-01-01'
                       ,'yyyy-mm-dd')
               ,6)
      ,next_day(to_date('1990-01-01'
                       ,'yyyy-mm-dd')
               ,1)
      ,last_day(to_date('1990-01-01'
                       ,'yyyy-mm-dd'))
      ,round(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'year')
      ,round(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'month')
      ,round(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'day')
      ,trunc(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'year')
      ,trunc(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'month')
      ,trunc(to_date('1990-05-12'
                    ,'yyyy-mm-dd')
            ,'day')
FROM   dual;


--sysdate 日期的格式是按照客户端用户设置的格式

--1.    日期时间间隔操作 
--当前时间减去7分钟的时间 
select sysdate,sysdate - interval '7' MINUTE from dual 
--当前时间减去7小时的时间 
select sysdate - interval '7' hour from dual 
--当前时间减去7天的时间 
select sysdate - interval '7' day from dual 
--当前时间减去7月的时间 
select sysdate,sysdate - interval '7' month from dual 
--当前时间减去7年的时间 
select sysdate,sysdate - interval '7' year from dual 
--时间间隔乘以一个数字 
select sysdate,sysdate - 8 *interval '2' hour from dual 

--2.日期到字符操作 
select sysdate,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual 
select sysdate,to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual 
select sysdate,to_char(sysdate,'yyyy-ddd hh:mi:ss') from dual 
select sysdate,to_char(sysdate,'yyyy-mm iw-d hh:mi:ss') from dual 
--参考oracle的相关关文档(ORACLE901DOC/SERVER.901/A90125/SQL_ELEMENTS4.HTM#48515) 

3. 字符到日期操作 
select to_date('2003-10-17 21:15:37','yyyy-mm-dd hh24:mi:ss') from dual 
具体用法和上面的to_char差不多。 

4. trunk/ ROUND函数的使用

select trunc(sysdate ,'YEAR') from dual 

select trunc(sysdate ) from dual 
select to_char(trunc(sysdate ,'YYYY'),'YYYY') from dual 

--5.oracle有毫秒级的数据类型 
--返回当前时间年月日小时分秒毫秒 
select to_char(current_timestamp(5),'DD-MON-YYYY HH24:MI:SSxFF') from dual; 
--返回当前时间的秒毫秒,可以指定秒后面的精度(最大=9) 
select to_char(current_timestamp(9),'MI:SSxFF') from dual; 

--转换函数

--数据类型转换

--1 显性数据类型转换

--2 隐形数据类型转换


--to_char(date,'format_model')
SELECT to_date('2014-7-25'
              ,'yyyy-mm-dd')
      ,to_number(to_char(SYSDATE
                        ,'yyyymmdd'))
      ,to_char(67)
      ,to_char(SYSDATE)
      ,to_char(SYSDATE
              ,'YEAR')
      ,to_char(SYSDATE
              ,'MM')
      ,to_char(SYSDATE
              ,'DD')
      ,to_char(SYSDATE
              ,'HH24:MI:SS AM')
      ,to_char(SYSDATE
              ,'DDspth')
      ,to_char(SYSDATE
              ,'DD "of" MONTH yyyy') AS hiredate
      ,to_char(SYSDATE
              ,'fmDD "of" MONTH yyyy') AS hiredate
      ,to_char(SYSDATE
              ,'DD "of" MONTH YEAR') AS hiredate
FROM   dual;
--to_char(number,'format_model')
--9 表示一个数字
--0 强制显示0
--$ 放一个美元占位符
--L 使用浮点本地币种符号
--. 显示一个小数点占位符
--, 显示一个千分位占位符


ALTER session SET nls_currency = '¥';


SELECT to_char(salary
              ,'L99,999.00') salary
FROM   employees
WHERE  employee_id = 100;


ALTER session SET nls_currency = '$';
SELECT to_char(salary
              ,'L99,999.00') salary
FROM   employees
WHERE  employee_id = 100;


-- to_number()
TO_NUMBER应用 正确与否
select TO_NUMBER('4456') from dual; √
select TO_NUMBER('$4,456','$9,999' )from dual; √
select TO_NUMBER('$4,456,455.000','$9,999,999,999,999.999' )from dual; √


select to_date('2011-2-22','YYYY-MM-DD') from dual;
select to_date('2-22-2011','MM-DD-YYYY') from dual;
select to_date('2011-FEB-22','YYYY-MON-DD') from dual;


--NVL (expr1, expr2)                   如果expr1为空,这返回expr2
--NVL2 (expr1, expr2, expr3)           如果expr1为空,这返回expr3(第2个结果)否则返回expr2
--NULLIF (expr1, expr2)                如果expr1和expr2相等,则返回空 如果expr1不为空,则返回expr1,结束;否则计算expr2,直到找到
--COALESCE (expr1, expr2, ..., exprn)  一个不为NULL的值 或者如果全部为NULL,也只能返回NULL了
--备注:上述参数的类型都需要相同,或者可以转换为相同类型的
SELECT emp.employee_id
      ,nvl(emp.commission_pct
          ,0)
      ,nvl2(emp.department_id
           ,emp.department_id
           ,007)
FROM   employees emp;


--多路选择函数
SELECT emp.employee_id
      ,emp.job_id
      ,CASE emp.employee_id
           WHEN 100 THEN
            'max'
           WHEN 101 THEN
            'max'
           WHEN 102 THEN
            'max'
           ELSE
            'min'
       END "RANK"
FROM   employees emp;


SELECT emp.employee_id
      ,emp.job_id
      ,decode(emp.employee_id
             ,100
             ,'max'
             ,101
             ,'max'
             ,102
             ,'max'
             ,'min') "RANK"
FROM   employees emp
WHERE  emp.employee_id < 200;


--第4单元 多表关联查询
--在执行多表查询时,若未指定链接条件,则结果返回是个笛卡尔乘积


--oracle 定义的链接查询
-- 1.等于链接
-- 2.不等链接
-- 3.外连接(可细分为 左外连接、右外连接)
-- 4.自链接


--等于连接
SELECT emp.employee_id
      ,dep.department_id
FROM   employees   emp
      ,departments dep
WHERE  emp.department_id = dep.department_id
;
--左外连接
SELECT emp.employee_id
      ,dep.department_id
FROM   employees   emp
      ,departments dep
WHERE  emp.department_id = dep.department_id(+)
;
--右外连接
SELECT emp.employee_id
      ,dep.department_id
FROM   employees   emp
      ,departments dep
WHERE  emp.department_id(+) = dep.department_id
;
--自链接
SELECT table1.column
      ,table2.column
FROM   table1
      ,table1 table2
WHERE  table1.column1 = table2.column2;


--SQL1999 链接
SELECT table1.column
      ,table2.column
FROM   table1
CROSS  JOIN table2 | NATURAL
JOIN   table2 |
JOIN   table2
USING  (column_name) |
JOIN   table2
ON     (table1.column_name = table2.column_name) |
LEFT   |
RIG    |
FULL   OUTER JOIN table2
ON     (table1.column_name = table2.column_name);


--1 交叉连接 :交叉连接相当于没有连接条件的多表关联查询,结果是个笛卡尔乘积。
--2 自然链接 :相当于Oracle的“等于连接”,只不过是让系统自己去找两张表中字段名相同的字段作为“等于连接”条件;(注意如果两个表中有相同的列名,但字段类型不一样,这会引发一个错误)
--3 using子句
SELECT e.employee_id, e.last_name, d.location_id
FROM employees e JOIN departments d
USING (department_id) ;
--4 内连接:相当于Oracle的“等于链接“
SELECT employee_id, city, department_name
FROM employees e 
INNER JOIN departments d ON d.department_id = e.department_id
INNER JOIN locations l ON d.location_id = l.location_id;
--5 外连接(全外连接、左外连接、右外连接)
--左外连接
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;


--右外连接
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;


--全外连接
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
FULL OUTER JOIN departments d
ON (e.department_id = d.department_id) ;

SELECT emp.*

FROMemployees emp

--WHERE ROWNUM =1 将第一行显示出来 先将表进行关联,再判断是否满足条件,如果是,则显示出来,如果不是,则过滤掉

--WHERE ROWNUM =10 不显示任何结果

--WHERE ROWNUM <=10 显示前10条记录

;


--第5 单元 分组计算函数和group by 子句
--常用的分组函数
--1、求和(SUM)
--2、求平均值(AVG)
--3、计数(COUNT)
--4、求标准差(STDDEV)
--5、求方差(VARIANCE)
--6、求最大值(MAX)
--7、求最小值(MIN)
--COUNT(*)  返回满足选择条件的所有行的行数,包括值为空的行和重复的行
--COUNT(expr) 返回满足选择条件的且表达式不为空行数。
--COUNT(DISTINCT expr) 返回满足选择条件的且表达式不为空,且不重复的行数。
--分组函数遇到null,直接忽略
SELECT AVG(salary)
      ,MAX(salary)
      ,MIN(salary)
      ,SUM(salary)
FROM   employees
WHERE  job_id LIKE '%REP%';
SELECT MIN(hire_date)
      ,MAX(hire_date)
FROM   employees;


SELECT AVG(salary) FROM employees
GROUP BY department_id ;




--最高部门的平均薪水
--having 下可以直接使用分组函数得到的结果
SELECT emp.department_id
      ,AVG(emp.salary)
FROM   employees emp
GROUP  BY emp.department_id
HAVING AVG(emp.salary) = (SELECT MAX(AVG(salary))
                          FROM   employees
                          GROUP  BY department_id);
                          
--第6单元 子查询
SELECT employee_id
      ,last_name
      ,job_id
      ,salary
FROM   employees
WHERE  salary < ANY (SELECT salary
        FROM   employees
        WHERE  job_id = 'IT_PROG')
AND    job_id <> 'IT_PROG';


--第7单元DML 语句
--插入语句
--方式一:写出表名+列名
--注意:在“列”中,对于不允许为NULL的列,必须写出来;对于允许为NULL的列,可以不写出来
--在Value中,对于列中未写出来的列,默认赋予NULL值
INSERT INTO departments (department_id,department_name )
VALUES (30, 'Purchasing' );

--方式二:仅写出表名
--注意:在Value中必须对应写出每个列的值,即是是允许NULL的字段,也必须显式的给出NULL
INSERT INTO departments
VALUES (100, 'Finance', NULL, NULL);

--方式三:从另一个表中Copy 一行
--语法:INSERT INTO table[ column(, column) ] subquery;
--注意:在这种方式下,不要使用VALUES 关键字
INSERT INTO sales_reps
    (id
    ,NAME
    ,salary
    ,commission_pct)
    SELECT employee_id
          ,last_name
          ,salary
          ,commission_pct
    FROM   employees
    WHERE  job_id LIKE '%REP%';


--更新语句
方式一:更新符合条件的行中某些列为具体的值
UPDATE employees
SET    department_id = 70
WHERE  employee_id = 113;

方式二:使用子查询的结果作为更新后的值
UPDATE employees
SET    job_id =
       (SELECT job_id
        FROM   employees
        WHERE  employee_id = 205)
      ,salary =
       (SELECT salary
        FROM   employees
        WHERE  employee_id = 205)
WHERE  employee_id = 114;


--删除语句
DELETE FROM departments
WHERE department_name = 'Finance';
--删除表中所有数据
DELETE FROM copy_emp;


--merge 根据条件进行查询,如果存在记录则更新,如果不存在则插入
MERGE INTO copy_emp c
USING employees e
ON (c.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
...
c.department_id = e.department_id
WHEN NOT MATCHED THEN
INSERT VALUES(e.employee_id, e.first_name, e.last_name,
e.email, e.phone_number, e.hire_date, e.job_id,
e.salary, e.commission_pct, e.manager_id, 
e.department_id);


--第8单元 事务控制
--ORACLE数据库通过事务来控制数据的一致性,当用户进程或者系统崩溃的时候,事务可提供用户更多的的灵活性和控制,以确保数据的一致性。


--当如下事件发生是,会隐式的执行Commit动作:
--1、数据定义语句被执行的时候,比如新建一张表:Create Table …
--2、数据控制语句被执行的时候,比如赋权GRANT …( 或者DENY)
--3、正常退出iSQL*Plus 或者PLSQL DEVELOPER, 而没有显式的执行COMMIT 或者ROLLBACK语句 。-


--当如下事件发生时,会隐式执行Rollback 动作:
--1、非正常退出iSQL*Plus , PLSQL DEVELOPER, 或者发生系统错误。


--在Commit 或者Rollback前后数据的状态:
--1、在数据已经被更改,但没有Commit前 ,被更改记录处于被锁定状态,其他用户无法进行更改;
--2、在数据已经被更改,但没有Commit前 ,只有当前Session的用户可以看到这种变更 ,其他Session的用户看不到数据的变化。
--3、在数据已经被更改,并且被Commit后,被更改记录自动解锁,其他用户可以进行更改;
--4、在数据已经被更改,并且被Commit后,其他Session的用户再次访问这些数据时,看到的是变化后的数据。
--当有用户修改数据时,Oracle先把那部分原始数据备份到回滚段,在Commit之前,其他Session用户读到的这部分数据是回滚段上的; 在提交之后,回滚段被释放


--第9单元 锁
--Oracle中的锁的主要作用就是:防止 并发事务对相同的资源(所谓资源是指 表、行、共享的数据结构、
--数据字典行等)进行更改的时候,相互破坏。
--锁有既有隐式的,也有显式的; 


--隐式枷锁:某用户对某一批数据进行更改,而未提交之前,Oracle会隐式的进行加锁;
--显示枷锁
Select … from TableA Where … For UPDATE NOWAIT


--查锁
SELECT a.*
      ,c.type
      ,c.lmode
FROM   v$locked_object a
      ,all_objects     b
      ,v$lock          c
WHERE  a.object_id = b.object_id
AND    a.session_id = c.sid
AND    b.object_name = 'TESTTAB3'


--第10单元 数据库对象--表
--数据库表中的数据类型
--VARCHAR2(size)                 可变长字符串
--CHAR(size)                     定长字符串
--NUMBER(p,s)                    可变长数值
--DATE                           日期时间
--LONG                           可变长大字符串,最大可到2G
--CLOB                           可变长大字符串数据,最大可到4G
--RAW and LONG RAW               二进制数据
--BLOB                           大二进制数据,最大可到4G
--BFILE                          存储于外部文件的二进制数据,最大可到4G
--ROWID                          64进制18位长度的数据,用以标识行的地址
--TIMESTAMP                      精确到分秒级的日期类型(9i以后提供的增强数据类型)
--INTERVAL YEAR TO MONTH         表示几年几个月的间隔(9i以后提供的增强数据类型-极其少见)
--INTERVAL DAY TO SECOND 表示几天几小时几分几秒的间隔(9i以后提供的增强数据类型-极其少见)


CREATE TABLE time_example
(order_date1 TIMESTAMP,
order_date2 TIMESTAMP WITH TIME ZONE,
order_date3 TIMESTAMP WITH LOCAL TIME ZONE); 

INSERT INTO time_example VALUES('15-NOV-00 09:34:28','15-NOV-00 09:34:28 AM -8:00',
'15-NOV-00 09:34:28 AM');

CREATE TABLEA as select * from tableb;

CREATE TABLEA as select * from tableb where 1=2;

--添加列:
ALTER TABLE table
ADD (column datatype[DEFAULT expr]
[, column datatype]...);
--更改列:
ALTER TABLE table
MODIFY (column datatype[DEFAULT expr]
[, column datatype]...);
--删除列:
ALTER TABLE table
DROP (column);

--删除表:
DROP TABLE tableName;
--注意:表被删 除后,任何依赖于这张表的视图、Package等数据库对象都自动变为无效:
--更改表名:
RENAME oldtablename to newtableName;
--一次性清空一张表中的所有内容,但保留表结构:
TRUNCATE TABLE tableName;
--注意TRUNCATE 与DELETE FROM table 的区别:1)没有Rollback机会2)HWM标记复位
--hwm 帮助寻找可供插入的空余空间


--第11单元:数据库对象--约束
--oracle 数据库使用“约束”来阻止对数据库表中数据的不合法的‘增删改’动作
--常用约束
--NOT NULL  (非空约束)
--UNIQUE  (唯一性约束)
--PRIMARY KEY  (主键约束)
--FOREIGN KEY  (外键约束)
--CHECK  (自定义约束)
--创建表的时候创建约束
CREATE TABLE employees(employee_id NUMBER(6)
                      ,first_name VARCHAR2(20)
                      ,.. . job_id VARCHAR2(10) NOT NULL
                      ,CONSTRAINT emp_emp_id_pk primary key(employee_id));


--单独创建约束
ALTER TABLE cux_les_je_lines add CONSTRAINT cux_les_je_lines_pk primary key(je_line_id);


CREATE TABLE employees(employee_id NUMBER(6)
                      ,last_name VARCHAR2(25) NOT NULL
                      ,salary NUMBER(8
                             ,2) CONSTRAINT emp_salary_min CHECK(salary > 0)
                      ,email VARCHAR2(25)
                      ,commission_pct NUMBER(2
                             ,2)
                      ,hire_date DATE CONSTRAINT emp_hire_date_nn NOT NULL
                      ,CONSTRAINT emp_dept_fk foreign key(department_id) references departments(department_id)
                      ,CONSTRAINT emp_email_uk UNIQUE(email)), CONSTRAINT dept_id_pk primary key(employee_id));


--外键约束类型:
-- REFERENCES: 表示列中的值必须在父表中存在
-- ON DELETE CASCADE: 当父表记录删除的时候自动删除子表中的相应记录.
-- ON DELETE SET NULL: 当父表记录删除的时候自动把子表中相应记录的值设为NULL


--删除约束:
ALTER TABLE employees drop CONSTRAINT emp_manager_fk;

ALTER TABLE departments drop primary key cascade;

ALTER TABLE employees disable CONSTRAINT emp_emp_id_pk cascade;

ALTER TABLE employees enable constraintemp_emp_id_pk;

CREATE TABLE test1(pk NUMBER primary key
                  ,fk NUMBER
                  ,col1 NUMBER
                  ,col2 NUMBER
                  ,CONSTRAINT fk_constraint foreign key(fk) references test1
                  ,CONSTRAINT ck1 CHECK(pk > 0 AND col1 > 0)
                  ,CONSTRAINT ck2 CHECK(col2 > 0));

ALTER TABLE test1 drop(pk);

--级联删除,比如你删除某个表的时候后面加这个关键字,会在删除这个表的同时删除和该表有关系的其他对象
ALTER TABLE test1 
DROP (pk) CASCADE CONSTRAINTS;
--参考原文:http://blog.csdn.net/kadwf123/article/details/8067381

--查询系统存在的约束
    SELECT constraint_name
          ,constraint_type
          ,search_condition
    FROM   user_constraints
    WHERE  table_name = 'EMPLOYEES';


--第12单元 数据库对象-视图
--为复杂查询的结果集创建视图,为以后的查询提供方便

--简单视图举例: 
CREATE view empvu80 AS
    SELECT employee_id
          ,last_name
          ,salary
    FROM   employees
    WHERE  department_id = 80;
--复杂视图举例: 
CREATE view dept_sum_vu(NAME, minsal, maxsal, avgsal) AS
    SELECT d.department_name
          ,MIN(e.salary)
          ,MAX(e.salary)
          ,AVG(e.salary)
    FROM   employees   e
          ,departments d
    WHERE  e.department_id = d.department_id
    GROUP  BY d.department_name;

drop view empvu80;

--TOP-N 查询
SELECT column_list
      ,rownum
FROM   (SELECT column_list
        FROM   TABLE
        ORDER  BY top - n_column)
WHERE  rownum <= n;


--第13单元 数据库对象-序列、索引、同意词
--序列:具有唯一性、自增长类型的数据库对象,每获取一次,就自动增长,保证下次获取时肯定不一样的值
--创建序列
CREATE sequence sequence increment BY n START WITH n {maxvalue n | nomaxvalue} {minvalue n | nominvalue} {cycle | nocycle} {cache n | nocache} ;


--序列使用举例
INSERT
    INTO departments(department_id
                    ,department_name
                    ,location_id) VALUES(dept_deptid_seq.nextval
                                        ,'Support'
                                        ,2500);


SELECT dept_deptid_seq.currval
FROM   dual;


--更改序列定义: 
ALTER sequence dept_deptid_seq increment BY 20 maxvalue 999999 nocache nocycle;
--删除序列: 
drop sequence dept_deptid_seq;


--索引:索引是有序的,可以使用诸如二分法子类的方法加快查询,而不是做全表扫描
--索引创建举例:
CREATE INDEX emp_last_name_idx ON employees(last_name);
--建立索引的条件
--查询条件使用的列范围跨度很大,要获取的数据量占整个表的数据总量小于4%
--不适合建立索引的情况:
--1被查询的表本身很小,数据库先是根据索引找到数据所在的位置,然后再在数据的位置提取数据,如果数据本身很小,全表扫描很快,建立索引需要二次扫描,消耗时间
--2要获取的数据量超过整个表的4%
--3数据表需要经常被更新,建立的索引页需要经常被更新,会影响性能


--同义词:简化写法
CREATE synonym table1 FOR b.table1


--第14 单元 控制用户权限
--创建用户
CREATE USER hpos identified BY hpos;
--设置用户表空间,表的存储空间,临时表空间
ALTER USER hpos DEFAULT tablespace hpos_data quota unlimited ON hpos_data;
ALTER USER hpos temporary tablespace temp;
--将各种权限赋值给用户
grant CREATE session, CREATE TABLE, CREATE PROCEDURE, CREATE sequence, CREATE TRIGGER, CREATE view, CREATE synonym, ALTER session TO hpos;
--resource包含基本权限 ,对表的增删改查
grant RESOURCE TO hpos;

--通过角色,分配权限
CREATE role manager;
grant CREATE TABLE, CREATE view TO manager;
grant manager TO xiaowu;

grant UPDATE(department_name
            ,location_id) ON departments TO xiaowu;

grant
    SELECT ,INSERT ON departments TO xiaowu WITH grant OPTION;
--with grant option 允许将权限转移给他人

grant
    SELECT ON        xiaowu.departments TO public
           --让所有人都有相关权限
           
           --数据字典视图
           --ROLE_SYS_PRIVS 角色对应的系统权限
           --ROLE_TAB_PRIVS 角色对应的表权限
           --USER_ROLE_PRIVS 用户的角色分配表
           --USER_TAB_PRIVS_MADE 用户对象上赋权者与被赋者的历史赋权情况
           --USER_TAB_PRIVS_RECD 用户对象上拥有者与被赋者的历史赋权情况
           --USER_COL_PRIVS_MADE 用户对象列上赋权者与被赋者的历史赋权情况
           --USER_COL_PRIVS_RECD 用户对象列上拥有者与被赋者的历史赋权情况
           --USER_SYS_PRIVS 用户的系统权限
           
           --收回权限
                   revoke {privilege
          ,privilege .. . | all} ON OBJECT
    FROM   {user
          , USER .. . | role | public}
           
           --创建DB-LINK,通过DB-LINK 访问另一数据库中的表
            CREATE public databaselink hq.acme.com
    USING  'sales';
DATABASE link created.
    SELECT *
    FROM   emp@hq.acme.com;

--第15单元 集合操作

--集合的合并
SELECT employee_id
      ,job_id
FROM   employees
UNION
SELECT employee_id
      ,job_id
FROM   job_history
;


SELECT employee_id
      ,job_id
      ,department_id
FROM   employees
UNION ALL
SELECT employee_id
      ,job_id
      ,department_id
FROM   job_history
ORDER  BY employee_id
;


--union 会去掉集合重复部分,作用过程也是全表扫描,会影响性能
--union all 不会去掉集合重复部分


--INTERSECT 交集
SELECT employee_id
      ,job_id
FROM   employees
INTERSECT
SELECT employee_id
      ,job_id
FROM   job_history;


--minus 取差集 
SELECT employee_id
      ,job_id
FROM   employees
MINUS
SELECT employee_id
      ,job_id
FROM   job_history;


--第16单元 group by 字句的增强
SELECT department_id
      ,job_id
      ,SUM(salary)
FROM   employees
WHERE  department_id < 60
GROUP  BY ROLLUP(department_id
                ,job_id);
--备注:先是查询同个部门同个工作总的工资,然后查询同个部门总的工资,然后查询所有部门(整个公司)总的工资 
SELECT department_id
      ,job_id
      ,SUM(salary)
FROM   employees
WHERE  department_id < 60
GROUP  BY CUBE(department_id
              ,job_id);
--备注:先是查询同个部门同个工作总的工资,然后查询同个部门总的工资,然后查询所有部门同种工作总的工资,
--然后就是全部部门所有工资总的工资


--查询根据属性列分配的源
SELECT department_id deptid
      ,job_id job
      ,SUM(salary)
      ,GROUPING(department_id) grp_dept
      ,GROUPING(job_id) grp_job
FROM   employees
WHERE  department_id < 50
GROUP  BY ROLLUP(department_id
                ,job_id);


SELECT department_id
      ,job_id
      ,manager_id
      ,AVG(salary)
FROM   employees
GROUP  BY GROUPING SETS((department_id, job_id),(job_id, manager_id));

--第17单元

--高于查询同个部门平均工资的员工
SELECT last_name
      ,salary
      ,department_id
FROM   employees
OUTER  WHERE salary > (SELECT AVG(salary)
                       FROM   employees
                       WHERE  department_id = outer.department_id);


--查询为领导的员工
SELECT employee_id
      ,last_name
      ,job_id
      ,department_id
FROM   employees
OUTER  WHERE EXISTS (SELECT 'X'
              FROM   employees
              WHERE  manager_id = outer.employee_id);


SELECT employee_id
      ,last_name
      ,job_id
      ,department_id
FROM   employees
WHERE  employee_id IN (SELECT manager_id
                       FROM   employees
                       WHERE  manager_id IS NOT NULL);


--查询没有员工的部门
SELECT department_id
      ,department_name
FROM   departments d
WHERE  NOT EXISTS (SELECT 'X'
        FROM   employees
        WHERE  department_id = d.department_id);


SELECT department_id
      ,department_name
FROM   departments
WHERE  department_id NOT IN (SELECT department_id
                             FROM   employees);


--in 属于全表查询操作,效率会下降很多


--工作记录大于两条的员工
SELECT e.employee_id
      ,last_name
      ,e.job_id
FROM   employees e
WHERE  2 <= (SELECT COUNT(*)
             FROM   job_history
             WHERE  employee_id = e.employee_id);


-- 暂存多表
WITH dept_costs AS
 (SELECT d.department_name
        ,SUM(e.salary) AS dept_total
  FROM   employees   e
        ,departments d
  WHERE  e.department_id = d.department_id
  GROUP  BY d.department_name),
avg_cost AS
 (SELECT SUM(dept_total) / COUNT(*) AS dept_avg
  FROM   dept_costs)
SELECT *
FROM   dept_costs
WHERE  dept_total > (SELECT dept_avg
                     FROM   avg_cost)
ORDER  BY department_name;




--第18单元 递归查询
--查询从King开始,从上往下的各级员工
SELECT employee_id || last_name || 'reports to ' || PRIOR last_name "Walk Top Down"
FROM   employees
START  WITH last_name = 'King' --从king 开始查询
CONNECT BY PRIOR employee_id = manager_id;
-- king 作为递归查询的第一层
-- king的employee_id = whose manager_id 作为条件,得到who


--查询从101开始,从下往上的各级员工
SELECT employee_id
      ,last_name
      ,job_id
      ,manager_id
      ,PRIOR employee_id
FROM   employees
START  WITH employee_id = 101
CONNECT BY PRIOR manager_id = employee_id;
--从下往上查询,101作为对底层,
--101的manager_id =empleoyee_id 得到上一层的id,
--prior 作为每层的串联关键


--从上往下查询
SELECT first_name
      ,lpad(last_name
           ,length(last_name) + (LEVEL * 2) - 2
           ,'_') AS org_chart
FROM   employees
START  WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id


--第19单元
--insert 增强
--选择不同字段,然后根据字段匹配,同时插入多个表
 INSERT ALL INTO sal_history VALUES(empid
                 ,hiredate
                 ,sal) INTO mgr_history VALUES(empid
                 ,mgr
                 ,sal)    SELECT employee_id empid
                    ,hire_date   hiredate
                    ,salary      sal
                    ,manager_id  mgr
              FROM   employees
              WHERE  employee_id > 200
              ;


CREATE TABLE mytable1(tableid NUMBER
                     ,tablex NUMBER);
CREATE TABLE mytable2(tableid NUMBER
                     ,tablex NUMBER);
CREATE TABLE mytable3(tableid NUMBER
                     ,tablex NUMBER);


--一个来源插入多个目标表(有条件,首次匹配即跳到下一条)
INSERT FIRST WHEN tableid < 200 THEN INTO mytable1
VALUES
    (tableid
    ,tablex) WHEN tablex < 10000 THEN INTO mytable2
VALUES
    (tableid
    ,tablex) ELSE INTO mytable3
VALUES
    (tableid
    ,tablex)
    SELECT employee_id tableid
          ,salary      tablex
    FROM   employees;


drop TABLE mytable1;
drop TABLE mytable2;
drop TABLE mytable3;


SELECT *
FROM   mytable1;
SELECT *
FROM   mytable2;
SELECT *
FROM   mytable3;
SELECT employee_id
      ,salary
FROM   employees;


--对表的操作
--修改表,增加表的列
ALTER TABLE employees add(department_name VARCHAR2(14));


UPDATE employees e
SET    department_name =
       (SELECT department_name
        FROM   departments d
        WHERE  e.department_id = d.department_id);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值