美文网首页
2018-12-18

2018-12-18

作者: twoapes | 来源:发表于2019-01-05 21:47 被阅读9次

ORACLE视频学习之SQL篇

视频观看地址
抖音号:huyingzhao

scott用户对应表字段备注

-- Add comments to the table 
comment on table SCOTT.EMP
  is '雇员表';
-- Add comments to the columns 
comment on column SCOTT.EMP.empno
  is '部门编号';
comment on column SCOTT.EMP.ename
  is '雇员姓名';
comment on column SCOTT.EMP.job
  is '雇员职位';
comment on column SCOTT.EMP.mgr
  is '雇员的经理';
comment on column SCOTT.EMP.hiredate
  is '雇员的雇佣日期';
comment on column SCOTT.EMP.sal
  is '雇员基本工资';
comment on column SCOTT.EMP.comm
  is '雇员的奖金';
comment on column SCOTT.EMP.deptno
  is '雇员所在部门的编号';
    
-- Add comments to the table 
comment on table SCOTT.DEPT
  is '部门表';
-- Add comments to the columns 
comment on column SCOTT.DEPT.DEPTNO
  is '部门编号';
comment on column SCOTT.DEPT.DNAME
  is '部门名称';
comment on column SCOTT.DEPT.LOC
  is '部门所在位置';  
    
-- Add comments to the table 
comment on table SCOTT.BONUS
  is '工资表';
-- Add comments to the columns 
comment on column SCOTT.BONUS.ENAME
  is '雇员姓名';
comment on column SCOTT.BONUS.SAL
  is '雇员基本工资';
comment on column SCOTT.BONUS.JOB
  is '雇员职位';
comment on column SCOTT.BONUS.COMM
  is '雇员的奖金';
    
    
-- Add comments to the table 
comment on table SCOTT.SALGRADE
is '工资等级表';
-- Add comments to the columns 
comment on column SCOTT.SALGRADE.GRADE
is '工资的等级';
comment on column SCOTT.SALGRADE.LOSAL
is '此等级的最低工资';
comment on column SCOTT.SALGRADE.HISAL
is '此等级的最高工资';

一次性向多个表插入记录

--一次性向多个表插入记录
SELECT s.dname, s.loc FROM scott.dept s WHERE s.deptno IN (10, 20, 30);
CREATE TABLE dept10 AS
  SELECT s.dname, s.loc FROM scott.dept s WHERE 1 = 0;
CREATE TABLE dept20 AS
  SELECT s.dname, s.loc FROM scott.dept s WHERE 1 = 0;
CREATE TABLE dept30 AS
  SELECT s.dname, s.loc FROM scott.dept s WHERE 1 = 0;
INSERT ALL WHEN deptno = 10 THEN INTO dept10
  (dname, loc)
VALUES
  (dname, loc) WHEN deptno = 20 THEN INTO dept20
  (dname, loc)
VALUES
  (dname, loc) WHEN deptno = 30 THEN INTO dept30
  (dname, loc)
VALUES
  (dname, loc)
  SELECT deptno, dname, loc FROM scott.dept;
COMMIT;
SELECT * FROM dept10; --ACCOUNTING  NEW YORK
SELECT * FROM dept20; --RESEARCH    DALLAS
SELECT * FROM dept30; --SALES   CHICAGO

--drop
drop table dept10;
drop table dept20;
drop table dept30;

两个表中查找共同行

--两个表中查找共同行
SELECT * FROM scott.emp s WHERE s.deptno = 10;
SELECT * FROM scott.emp o WHERE o.ename = 'KING';
--使用INTERSECT取交集
SELECT *
  FROM scott.emp s
 WHERE s.deptno = 10
INTERSECT
SELECT *
  FROM scott.emp s
 WHERE s.ename = 'KING';

为列取有意义的名字

--为列取有意义的名字
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno = 10;
--通过直接字段+空格(或AS)+要取的名字(不能有特殊符号,例如花括号,小括号,表达式等)
SELECT s.empno    部门编号,
       s.ename    雇员姓名,
       s.job      雇员职位,
       s.mgr      雇员的经理,
       s.hiredate AS 雇员的雇佣日期,
       s.sal      AS 雇员基本工资,
       s.comm     AS 雇员的奖金,
       s.deptno   AS 雇员所在部门的编号
  FROM scott.emp s
 WHERE s.deptno = 10;
--通过直接字段+空格(或AS)+要取的名字(需要含有特殊符号,例如花括号,小括号,表达式等)
SELECT 
       --s.empno    AS "此"部门"编号", 双引号内不能包含双引号
       s.ename    AS 雇员姓名,
       s.job      AS 雇员职位,
       s.mgr      AS 雇员的经理,
       s.hiredate AS "雇员的雇佣日期(yyyy-mm-dd)",
       s.sal      AS 雇员基本工资,
       s.comm     AS "雇员的奖金{没有奖金就是空值!}",
       s.deptno   AS 雇员所在部门的编号
  FROM scott.emp s
 WHERE s.deptno = 10;
----注意:如果区别名为中文名,注意获取sql时对应的字符集,防止乱码,或尽量不使用中文和特殊符号

从一个表中向另一个表中复制行

--从一个表中向另一个表中复制行
SELECT * FROM scott.dept;
--假设以下为复制的数据
SELECT '50', s.dname, s.loc FROM scott.dept s WHERE s.deptno = '40';
INSERT INTO scott.dept
  SELECT '50', s.dname, s.loc FROM scott.dept s WHERE s.deptno = '40';
COMMIT;
SELECT s.deptno, s.dname, s.loc FROM scott.dept s WHERE s.deptno = '50';


--不影响scott用户脚本
DELETE FROM scott.dept s WHERE s.deptno = '50';
COMMIT;

从一个表中查找另一个表中没有的值

--从一个表中查找另一个表中没有的值
SELECT * FROM scott.emp s WHERE s.deptno = 10;
SELECT * FROM scott.emp o WHERE o.ename = 'KING';
--使用MINUS取差集
SELECT *
  FROM scott.emp s
 WHERE s.deptno = 10
MINUS
SELECT *
  FROM scott.emp o
 WHERE o.ename = 'KING';
--使用NOT EXISTS取另一个表中没有的值
SELECT *
  FROM scott.emp s
 WHERE s.deptno = 10
   AND NOT EXISTS (SELECT 1
          FROM scott.emp o
         WHERE o.ename = 'KING'
           AND s.empno = o.empno)

从字符串中删除不需要的字符

--从字符串中删除不需要的字符
SELECT * FROM scott.dept s WHERE s.deptno = 10;
SELECT s.dname FROM scott.dept s WHERE s.deptno = 10;
SELECT REPLACE(s.dname, 'CC', '') AS remove_dname
  FROM scott.dept s
 WHERE s.deptno = 10;

从表中删除所有记录

--从表中删除所有记录
select * from scott.emp;
delete scott.emp;
select * from scott.emp;
rollback;


--还原操作
rollback;

从表中检索部分列

--从表中检索部分列
select s.empno,s.ename,s.job from scott.emp s;
select s.empno,s.ename from scott.emp s;
select s.empno,s.ename,s.deptno from scott.emp s;

从表中检索部分行

--从表中检索部分行
--工资大于1600的员工
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal > 1600;
--工资小于1600的员工
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal < 1600;
--工资在800到1600之间的员工
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal BETWEEN 800 AND 1600;
--工资等于1600的员工
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal = 1600;
--工资不等于1600的员工
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal <> 1600;
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal ^= 1600;
SELECT s.sal, s.* FROM scott.emp s WHERE s.sal != 1600;

从表中选取所有的行和列

--从表中选取所有的行和列
select * from scott.emp;

以指定的次序返回查询结果

--以指定的次序返回查询结果
SELECT * FROM scott.emp s WHERE s.empno > 7499 ORDER BY s.empno ASC; --顺序
SELECT * FROM scott.emp s WHERE s.empno > 7499 ORDER BY s.empno DESC; --倒序
SELECT * FROM scott.emp s WHERE s.empno > 7499 ORDER BY s.ename ASC; --默认,如果是字符串,英文按照a到z,A-Z排序,同理中文按照拼音的字母排序,特殊符号按ACCII码排序

--汉字排序
--按照笔划排序
SELECT *
  FROM scott.emp s
 ORDER BY nlssort(s.ename, 'NLS_SORT=SCHINESE_STROKE_M');
--按照部首排序
SELECT *
  FROM scott.emp s
 ORDER BY nlssort(s.ename, 'NLS_SORT=SCHINESE_RADICAL_M');
--按照拼音排序,此为系统的默认排序方式
SELECT *
  FROM scott.emp s
 ORDER BY nlssort(s.ename, 'NLS_SORT=SCHINESE_PINYIN_M');

使用NULL代替默认值

--使用NULL代替默认值
--事实上有些字段如果需要默认值为NULL,其实可以直接插入进去
INSERT INTO scott.dept VALUES ('50', '行政部门', NULL);
SELECT * FROM scott.dept s WHERE s.loc IS NULL;
ROLLBACK;

使用SQL来生成SQL

--使用SQL来生成SQL
SELECT ('select count(1) from ' || s.table_name || ';') AS sql_table
  FROM user_tables s;


select count(1) from HYZ_DATABASE_DESIGN;
select count(1) from HYZ_DICTIONARY_USER;
select count(1) from HYZ_LOG;
select count(1) from HYZ_PATH;
select count(1) from HYZ_USER_LOGIN;
select count(1) from HYZ_COPY;

列出模式中的表

--列出模式中的表
SELECT * FROM all_tables s WHERE s.owner = 'SYSTEM'; --需要管理员权限
SELECT * FROM all_tables s WHERE s.owner = 'HUYINGZHAO'; --需要管理员权限
SELECT * FROM all_tables s WHERE s.owner = 'SCOTT'; --需要管理员权限

列出表中的列

--列出表中的列
SELECT * FROM all_tab_cols s WHERE s.owner = 'SYSTEM'; --需要管理员权限
SELECT * FROM all_tab_cols s WHERE s.owner = 'HUYINGZHAO'; --需要管理员权限
SELECT *
  FROM all_tab_cols s
 WHERE s.owner = 'HUYINGZHAO'
   AND s.table_name = 'HYZ_LOG'; --需要管理员权限 HYZ_LOG

列出表的索引列

--列出表的索引列
SELECT * FROM all_ind_columns s; --需要管理员权限
SELECT * FROM all_ind_columns s WHERE s.index_owner = 'HUYINGZHAO'; --需要管理员权限
SELECT * FROM all_ind_columns s WHERE s.index_owner = 'SCOTT'; --需要管理员权限

列出表约束

--列出表约束
SELECT * FROM all_constraints s; --需要管理员权限
SELECT * FROM all_constraints s WHERE s.index_owner = 'HUYINGZHAO'; --需要管理员权限
SELECT * FROM all_constraints s WHERE s.index_owner = 'SCOTT'; --需要管理员权限

删除单个记录

--删除单个记录
SELECT * FROM scott.emp s WHERE s.empno = 7782;
--通过条件为唯一约束或主键确定即可查询出单条数据,此时就可放心执行操作
DELETE scott.emp s WHERE s.deptno = 7782;
SELECT * FROM scott.emp s WHERE s.deptno = 7782;

--还原记录
rollback;

删除指定记录

--删除指定记录
SELECT * FROM scott.emp s WHERE s.deptno = 10;
DELETE scott.emp s WHERE s.deptno = 10;
SELECT * FROM scott.emp s WHERE s.deptno = 10;

--还原记录
rollback;

删除违反参照完整性的记录

--删除违反参照完整性的记录
SELECT *
  FROM scott.emp s
 WHERE NOT EXISTS (SELECT 1 FROM scott.dept o WHERE s.deptno = o.deptno);
DELETE scott.emp s
 WHERE NOT EXISTS (SELECT 1 FROM scott.dept o WHERE s.deptno = o.deptno);
DELETE scott.emp s
 WHERE s.deptno NOT IN
       (SELECT o.deptno FROM scott.dept o WHERE s.deptno = o.deptno);
       
       
--还原记录
rollback;

删除重复数据

--删除重复数据
CREATE TABLE TMP( ID NUMBER, V VARCHAR2(20));
insert into TMP(ID,V) values(1,'x');
insert into TMP(ID,V) values(2,'x');
insert into TMP(ID,V) values(3,'y');
insert into TMP(ID,V) values(4,'y');
insert into TMP(ID,V) values(5,'y');
insert into TMP(ID,V) values(6,'z');
insert into TMP(ID,V) values(7,'z');
insert into TMP(ID,V) values(8,'z');
insert into TMP(ID,V) values(9,'z');
insert into TMP(ID,V) values(9,'yz');
commit;
select * from TMP;
SELECT MIN(s.id),s.v FROM tmp s GROUP BY s.v;
delete tmp a where a.id in (SELECT MIN(s.id) FROM tmp s GROUP BY s.v);
commit;
select * from TMP;

--还原
drop table TMP;

合并记录

--合并记录
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 ORDER BY s.deptno;
CREATE TABLE emp_commission AS
  SELECT s.deptno, s.empno, s.ename, s.comm
    FROM scott.emp s
   WHERE s.ename IN ('CLARK', 'KING', 'MILLER');
SELECT * FROM emp_commission;
MERGE INTO emp_commission ec
USING (SELECT s.empno,
              s.ename,
              s.job,
              s.mgr,
              s.hiredate,
              s.sal,
              s.comm,
              s.deptno
         FROM scott.emp s) emp
ON (ec.empno = emp.empno)
--MATCHED返回表emp_commission含有scott.emp的记录
WHEN MATCHED THEN
  UPDATE SET ec.comm = 1000 DELETE WHERE sal < 2000
--NOT MATCHED返回表emp_commission不含有scott.emp的记录
WHEN NOT MATCHED THEN
  INSERT
    (ec.empno, ec.ename, ec.deptno, ec.comm)
  VALUES
    (emp.empno, emp.ename, emp.deptno, emp.comm);
COMMIT;
SELECT * FROM emp_commission;

--还原操作
DROP TABLE emp_commission;

向查询中增加联接而不影响其他联接

--向查询中增加联接而不影响其他联接
SELECT * FROM scott.emp;
SELECT * FROM scott.dept;
SELECT * FROM scott.salgrade;
SELECT s.deptno,
       s.dname,
       s.loc,
       's <--> o',
       o.empno,
       o.ename,
       o.job,
       o.mgr,
       o.hiredate,
       o.sal,
       o.comm,
       o.deptno,
       'o <--> t',
       t.grade
  FROM scott.dept s
  JOIN scott.emp o
    ON s.deptno = o.deptno
  JOIN scott.salgrade t --只需要根据工资高低就可以定义等级了,不含奖金
    ON o.sal BETWEEN t.losal AND t.hisal

在ORACLE中描述数据字典视图

--在ORACLE中描述数据字典视图
--dictionary用于查询视图或表的说明
select * from dictionary;
select * from dictionary s where s.TABLE_NAME='USER_TABLES';

--dict_columns用于查询视图或表的对应列说明
select * from dict_columns;
select * from dict_columns s where s.TABLE_NAME='USER_TABLES';

在SLEECT语句中使用条件逻辑

--在SLEECT语句中使用条件逻辑
SELECT
--部门编号在7369到7499返回0,否则1
 (CASE
   WHEN s.empno BETWEEN 7369 AND 7499 THEN
    '0'
   ELSE
    '1'
 END) AS case_empno,
 --部门编号是7369返回0,否则1
 (CASE s.empno
   WHEN 7369 THEN
    '0'
   ELSE
    '1'
 END) AS case_empno2,
 --部门编号是7369返回0,否则1
 decode(s.empno, 7369, 0, 1) AS case_empno2,
 s.*
  FROM scott.emp s
 WHERE s.deptno = 20
    OR s.deptno = 30;

在where子句中引用取别名的列

--在where子句中引用取别名的列
SELECT *
  FROM (SELECT s.empno,
               s.ename,
               s.job,
               s.mgr,
               s.hiredate,
               s.sal,
               s.comm,
               s.deptno AS 雇员所在部门的编号
          FROM scott.emp s
         WHERE s.deptno >= 10)
 WHERE 雇员所在部门的编号 = 10;

在一个表中查找与其他表不匹配的记录

--在一个表中查找与其他表不匹配的记录
SELECT * FROM scott.emp;
SELECT * FROM scott.dept;
--查找scott.emp在scott.dept表中不存在的记录,明显通过上面的语句可以看出,雇员表没有部门编号为40的成员
SELECT s.deptno,
       s.dname,
       s.loc,
       's <--> o',
       o.empno,
       o.ename,
       o.job,
       o.mgr,
       o.hiredate,
       o.sal,
       o.comm,
       o.deptno
  FROM scott.dept s
  JOIN scott.emp o
    ON s.deptno = o.deptno(+)
--WHERE o.deptno IS NOT NULL;

在表中编辑记录

--在表中编辑记录
SELECT s.deptno, s.dname, s.loc
  FROM scott.dept s
 WHERE s.deptno IN (10, 20);
UPDATE scott.dept s SET s.dname = 'RESEARCH' WHERE s.deptno = 10;
UPDATE scott.dept s SET s.dname = 'ACCOUNTING' WHERE s.deptno = 20;
COMMIT;
SELECT s.deptno, s.dname, s.loc
  FROM scott.dept s
 WHERE s.deptno IN (10, 20);
 
--还原值
UPDATE scott.dept s SET s.dname = 'ACCOUNTING' WHERE s.deptno = 10;
UPDATE scott.dept s SET s.dname = 'RESEARCH' WHERE s.deptno = 20;
COMMIT;

在表中随机返回N条记录

--在表中随机返回N条记录
SELECT s.ename, s.job FROM scott.emp s ORDER BY dbms_random.value();
SELECT *
  FROM (SELECT s.ename, s.job FROM scott.emp s ORDER BY dbms_random.value())
 WHERE rownum <= 5;

在运算和比较时,使用NULL

--在运算和比较时,使用NULL
SELECT * FROM scott.emp s;
SELECT * FROM scott.emp s WHERE s.ename = 'WARD';
SELECT *
  FROM scott.emp s
 WHERE coalesce(s.comm, 0) <=
       (SELECT coalesce(o.comm, 0) FROM scott.emp o WHERE o.ename = 'WARD');
SELECT *
  FROM scott.emp s
 WHERE nvl(s.comm, 0) <=
       (SELECT nvl(o.comm, 0) FROM scott.emp o WHERE o.ename = 'WARD');

处理排序空值

--处理排序空值
SELECT * FROM scott.emp s ORDER BY s.comm;
SELECT * FROM scott.emp s ORDER BY s.comm DESC;
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.comm,
       s.deptno,
       --通过标志0,1或NULL,NOTNULL返回不同的结果,区别是否为NULL,既不影响效率也不影响查询结果顺序
       decode(s.comm, NULL, 'NULL', 'NOTNULL') AS comm_is_null
  FROM scott.emp s;

复制表定义

--复制表定义
SELECT * FROM user_tables s WHERE s.table_name = 'DEPT'; --查询当前用户表,以确定当前用户没有此表
SELECT * FROM scott.dept;
--如果没有同名表,可以直接创建了
CREATE TABLE dept AS
  SELECT s.deptno, s.dname, s.loc FROM scott.dept s;
SELECT * FROM user_tables s WHERE s.table_name = 'DEPT'; --查询当前用户表,以确定当前用户已创建此表
SELECT * FROM dept;
drop TABLE dept;
--如果只是创建另一个表相同的表结构,而不包含数据,可以用以下语句
CREATE TABLE dept AS
  SELECT s.deptno, s.dname, s.loc FROM scott.dept s WHERE 1 = 0;
SELECT * FROM dept;
drop TABLE dept;

字符串文字中包含引号

--字符串文字中包含引号
--dual是一张虚表,它在数据库中创建用户后就会存在,因此无需创建
--以下四个字段都是实现字符串中含有分号方法
SELECT q'{'123,321'}' AS test_1,q'['123,321']' AS test_2,q'('123,321')' AS test_3,'''123,321''' AS test_4 FROM dual;

对字母数字混合的数据排序

--对字母数字混合的数据排序
SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
  FROM scott.emp s;
--以下语句可以理解把上面的查询当成一张V表来使用
WITH v AS
 (SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
    FROM scott.emp s)
SELECT * FROM v;

--使用一般表达式对V表的ename_deptno的数字排序
WITH v AS
 (SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
    FROM scott.emp s)
SELECT s.ename, s.deptno, ename_deptno,REPLACE(ename_deptno,REPLACE(translate(ename_deptno, '0123456789', '########'),'#',''),'') AS deptno_num
  FROM v s
 ORDER BY deptno_num;
 
--使用一般表达式对V表的ename_deptno的字符串排序
WITH v AS
 (SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
    FROM scott.emp s)
SELECT s.ename, s.deptno, ename_deptno,REPLACE(translate(ename_deptno, '0123456789', '########'),'#','') AS ename_str
  FROM v s
 ORDER BY ename_str;
 
 --使用正则表达式对V表的ename_deptno字段的数字排序
WITH v AS
 (SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
    FROM scott.emp s)
SELECT s.ename, s.deptno, ename_deptno,regexp_substr(s.ename_deptno,'[0-9]+') AS deptno_num
  FROM v s
 ORDER BY deptno_num;
--使用正则表达式对V表的ename_deptno字段的字符串排序
WITH v AS
 (SELECT s.ename, s.deptno, s.ename || ' ' || s.deptno AS ename_deptno
    FROM scott.emp s)
SELECT s.ename, s.deptno, ename_deptno,regexp_substr(s.ename_deptno,'[a-z A-Z]+') AS ename_str
  FROM v s
 ORDER BY ename_str;

将空值转换为实际值

--将空值转换为实际值
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.deptno,
       s.comm,
       --使用coalesce函数
       coalesce(s.comm, 0) AS coalesce_comm,
       --使用nvl函数
       nvl(s.comm, 0) AS nvl_comm,
       --使用decode
       decode(s.comm, NULL, 0, s.comm) AS decode_comm,
             --使用case...when
             (CASE WHEN s.comm IS NULL THEN 0 ELSE s.comm END ) AS case_comm
  FROM scott.emp s;

按多个字段排序

--按多个字段排序
SELECT s.empno,s.ename,s.job FROM scott.emp s;
SELECT s.empno,s.ename,s.job FROM scott.emp s ORDER BY s.empno,s.ename,s.job; --越放前面优先级越高
SELECT s.empno,s.ename,s.job FROM scott.emp s ORDER BY s.ename,s.empno,s.job; --越放前面优先级越高
SELECT s.empno,s.ename,s.job FROM scott.emp s ORDER BY 1,2,3; --越放前面优先级越高,但此方法不推荐使用,因为会让人大惑不解
SELECT s.empno,s.ename,s.job FROM scott.emp s ORDER BY 1,2,3; --越放前面优先级越高,但此方法不推荐使用,因为会让人大惑不解

按子串排序

--按子串排序
SELECT s.ename,
       s.job,
       --取ename字符串中最后一个字符的前两个字符串
       substr(s.ename, length(s.ename) - 2, 2) AS substr_ename
  FROM scott.emp s; --不排序
SELECT s.ename,
       s.job,
       --取ename字符串中最后一个字符的前两个字符串
       substr(s.ename, length(s.ename) - 2, 2) AS substr_ename
  FROM scott.emp s
 ORDER BY substr(s.ename, length(s.ename) - 2, 2);  --按substr_ename排序
--order by时可以使用别名,效果完全一样
SELECT s.ename,
       s.job,
       --取ename字符串中最后一个字符的前两个字符串
       substr(s.ename, length(s.ename) - 2, 2) AS substr_ename
  FROM scott.emp s
 ORDER BY substr_ename; --按substr_ename排序

按模式搜索

--按模式搜索

SELECT * FROM scott.emp s WHERE s.ename LIKE '%S'; --搜索雇员名字末尾字符带S的,%占多位
SELECT * FROM scott.emp s WHERE s.ename LIKE 'S%'; --搜索雇员名字首字符带S的,%占多位
SELECT * FROM scott.emp s WHERE s.ename LIKE '%S%'; --搜索雇员名字内带S的,%占多位
SELECT * FROM scott.emp s WHERE s.ename LIKE '_L%'; --搜索雇员名字第二个字符带L的,"_"占一位
SELECT * FROM scott.emp s WHERE s.ename LIKE 'A_L%'; --搜索雇员名A开头的第二个字符带L的,"_"占一位

插入新记录

--插入新记录
SELECT * FROM scott.dept;
--插入新部门编号,部门名称,部门所在位置
INSERT INTO scott.dept VALUES ('50', '行政部门', '深圳');
COMMIT; --提交,执行此步同一事务下的操作将完成记录,无法还原操作
ROLLBACK; --回滚,执行此步同一事务下的操作将被还原(后悔药)

--因此rollback后数据不会插入到scott.dept中,只有commit后才会被插入到scott.dept中
--注意:执行操作时,涉及到更改数据,例如增删改等,必须执行commit或rollback以便完成事务的完整性,如果事务不完整,会发生锁表或资源占用等异常情况
--当发生资源暂用或者锁表,可以使用管理员身份执行强制关闭事务,也可以断开相应占用的数据库连接,当数据库连接断开后,事务将不再发生,也就不存在锁表了

--还原数据
DELETE FROM scott.dept s WHERE s.deptno = '50';
COMMIT;

插入默认值

--插入默认值
SELECT * FROM scott.dept;
ALTER TABLE scott.dept modify loc DEFAULT '深圳';
COMMIT;
INSERT INTO scott.dept VALUES ('50', '行政部门', DEFAULT);
COMMIT;
SELECT s.deptno, s.dname, s.loc FROM scott.dept s WHERE s.deptno = '50';


--后期视频为保障scott用户的表不受影响,在不影响每一视频功能实现情况下,使用一些脚本还原操作,所以视频不会执行
DELETE FROM scott.dept s WHERE s.deptno = '50';
COMMIT;
ALTER TABLE scott.dept modify loc DEFAULT null;
COMMIT;

查找满足多个条件的行

--查找满足多个条件的行
--例如:需要查询工作为'SALESMAN',入职日期为1982年2月20号之后的员工
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.job = 'SALESMAN'
   AND s.hiredate > DATE '1981-02-20';
--例如:需要查询工作为'SALESMAN',入职日期为1982年2月20号之前的员工
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.job = 'SALESMAN'
   AND s.hiredate <= DATE '1981-02-20';
--例如:需要查询工作为'SALESMAN'并且入职时间为1982年2月20号之前或部门编号为10或没有奖金的员工
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.job = 'SALESMAN'
   AND (s.hiredate <= DATE
        '1981-02-20' OR s.deptno = '10' OR s.comm IS NOT NULL);
--例如:需要查询工作为'SALESMAN'或入职时间为1982年2月20号之前或部门编号为10或没有奖金的员工
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.job = 'SALESMAN'
    OR (s.hiredate <= DATE
        '1981-02-20' OR s.deptno = '10' OR s.comm IS NOT NULL);

查找空值

--查找空值
SELECT * FROM scott.emp s WHERE s.mgr IS NULL;
SELECT * FROM scott.emp s WHERE s.comm IS NOT NULL;
--空格和NULL不是一回事,空格仍有占位,而NULL表示什么都没有,可以这样理解
SELECT * FROM scott.emp s WHERE (s.job) = ' ';
SELECT * FROM scott.emp s WHERE TRIM(s.job) IS NULL;
SELECT * FROM scott.emp s WHERE (s.job) IS NULL;

根据数据项的键排序

--根据数据项的键排序
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.comm,
       s.deptno,
       --当工作为SALESMAN时按comm排序,否则按sal排序
       decode(s.job, 'SALESMAN', s.comm, s.sal) AS jpx --此行可以放在order by上,可以不显示出来
  FROM scott.emp s
 ORDER BY jpx;
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 ORDER BY decode(s.job, 'SALESMAN', s.comm, s.sal) --当工作为SALESMAN时按comm排序,否则按sal排序

组合相关的行

----组合相关的行
SELECT * FROM scott.emp s WHERE s.deptno = 10;
SELECT * FROM scott.dept o WHERE o.deptno = 10;
--可以使用内部条件连接两个表
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.comm,
       s.deptno,
       's <--> o',
       o.deptno,
       o.dname,
       o.loc
  FROM scott.emp s, scott.dept o
 WHERE s.deptno = o.deptno
   AND s.deptno = 10;
--可以使用JOIN连接两个表
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.comm,
       s.deptno,
       's <--> o',
       o.deptno,
       o.dname,
       o.loc
  FROM scott.emp s
  JOIN scott.dept o
    ON s.deptno = o.deptno --ON后面是两表或多表关联时的条件,也可以放在where后,但是不推荐,一般ON后面会更让人一看就懂
 WHERE s.deptno = 10;

聚集与联接

--聚集与联接
SELECT s.ename, s.job, s.mgr, s.hiredate, s.deptno, SUM(s.sal) AS sum_sal
  FROM scott.emp s
  JOIN scott.dept o
    ON s.deptno = o.deptno
   AND s.deptno = 20
 GROUP BY s.ename, s.job, s.mgr, s.hiredate, s.deptno
 ORDER BY s.job;
--如果GROUP BY使用不同,统计的合计含义也会改变,如下是统计雇员的经理,雇员所在部门的编号同一个工作的工资合计
SELECT s.job, s.mgr, s.deptno, SUM(s.sal) AS sum_sal
  FROM scott.emp s
  JOIN scott.dept o
    ON s.deptno = o.deptno
   AND s.deptno = 20
 GROUP BY s.job, s.mgr, s.deptno
 ORDER BY s.job;

记录集叠加

--记录集叠加
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno <= 10;
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno <= 20;
--UNION ALL上下两条或多条SQL必须元数据(字段名称,属性等)完全一致,使用UNION ALL取并集
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno <= 10
UNION ALL
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno <= 20;
--UNION和UNION ALL用法一致,但是UNION不仅去除重复,还会按字段顺序排序(以下empno优先级最高,按此排序)
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno = 10
UNION
SELECT s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno
  FROM scott.emp s
 WHERE s.deptno = 20;

识别和消除笛卡尔积

--识别和消除笛卡尔积
SELECT * FROM scott.emp;
SELECT * FROM scott.dept;
--如果条件加的不合理或少条件,会导致垃圾数据的产生
SELECT s.empno,
       s.ename,
       s.job,
       s.mgr,
       s.hiredate,
       s.sal,
       s.comm,
       s.deptno,
       's <--> o',
       o.deptno,
       o.dname,
       o.loc
  FROM scott.emp s
  LEFT JOIN scott.dept o
    ON s.deptno = 10
   --where s.deptno = o.deptno
--所以为解决这个问题,两表的数据关联关系必须搞清楚,两边有共同的数据一定要关联起来,这样减少垃圾数据产生之后,合理根据需要筛选数据

连接列值

--连接列值
SELECT s.ename, s.ename FROM scott.emp s;
SELECT s.ename || '的工作是' || s.ename AS name_job FROM scott.emp s;
SELECT concat(concat(s.ename, '的工作是'), s.ename) AS name_job
  FROM scott.emp s;
--在ORACLE中"||"是concat(var1,var2)函数的简写

限制返回行数

--限制返回行数
SELECT * FROM scott.emp s;
SELECT * FROM scott.emp s WHERE rownum <= 10;
SELECT * FROM scott.emp s WHERE rownum <= 1;
--ORACLE约定,ROWNUM函数不能使用大于符号,否则不会有数据返回
SELECT * FROM scott.emp s WHERE rownum > 1;
--由于ROWNUM函数返回最小值为1,因此,1>0永远成立,所以如果使用>0条件查询时结果为所有数据
SELECT * FROM scott.emp s WHERE rownum > 0;
--把ROWNUM函数作为字段,可以使用分页查询,此时可以使用>符号,它将拥有和字段一样的属性
SELECT *
  FROM (SELECT s.empno, s.ename, rownum AS n
          FROM scott.emp s
         WHERE rownum <= 14)
 WHERE n >= 10;

相关文章

网友评论

      本文标题:2018-12-18

      本文链接:https://www.haomeiwen.com/subject/lqalkqtx.html