DB基础

  • 通过deptno吧emp表和dept表查出来,如果deptno为空,则用deptno2
select * from scott.emp e,scott.dept d where (case when e.deptno is null then e.deptno2 else to_char(e.deptno) end)=d.deptno;
  • sql性能测试
    windows环境下cmd控制台或者sqlplus里执行测试sql语句执行时间和吞吐量命令
    set timing on
    set autot on
    但sqlplus里要更精准一些,因为cmd里是调用sqlplus执行的。

  • where 1=1作用
    这段代码应该是由程序(例如Java)中生成的,where条件中 1=1 之后的条件是通过 if 块动态变化的。例如:
    String sql=”select * from table_name where 1=1”;
    if( conditon 1) {
    sql=sql+” and var2=value2”;
    }
    if(conditon 2) {
    sql=sql+” and var3=value3”;
    }
    where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。

  • (+)和left join on的转换
    可以参考如下语句,其中语句1是left join用法,语句2是(+)用法。
    1、select 列名 from 表1 left join 表2 on 条件
    2、select 列名 from 表1 ,表2 where 表1.条件=表2.条件(+)
    关于使用(+)的一些注意事项:
    *(+)操作符只能出现在where子句中,并且不能与outer join语法同时使用。

  • 当使用(+)操作符执行外连接时,如果在where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符
    *(+)操作符只适用于列,而不能用在表达式上。
    *(+)操作符不能与or和in操作符一起使用。
    *(+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。

  • having语句
    having是对查询结果进行二次加工
    分组后,你还想加排除条件,就用having
    group by 之后不能使用where,所以需要having

DB基础_第1张图片

从下到上,从右到左。

  • count(*)和count(1)
    后者比前者效率高,因为不需要匹配。

  • in,exists区别
    在ORACLE 11G大行其道的今天,还有很多人受早期版本的影响,记住一些既定的规则,
    1.子查询结果集小,用IN
    2.外表小,子查询表大,用EXISTS
    这是完全错误的观点。在8i时代,这经常是正确的,但是现在已经11G了,马上12C就要面世了。其实在ORACLE 9i CBO就已经优化了IN,EXISTS的区别,ORACLE优化器有个查询转换器,很多SQL虽然写法不同,但是ORACLE优化器会根据既定规则进行查询重写,重写为优化器觉得效率最高的SQL,所以可能SQL写法不同,但是执行计划却是完全一样的。
    IN与EXISTS有一点要记住:IN一般是用于非相关子查询,而EXISTS一般用于相关子查询。
    相关子查询和非相关子查询的区别

  • 分页

 select * from (select rownum no, e.* from (select * from scott.emp e1 order by e1.sal,e1.deptno desc) e where rownum <= 5) where no >= 3;
select * from (select rownum no, e.* from (select * from scott.emp e1 order by e1.sal,e1.deptno desc) e) where no >= 3 and no <= 5;

区别:第一句只要找出前面5条排序就行了,后面那句得全部排序

  • 子查询的区别
    select * from (select * from scott.emp e order by e.sal desc) where rownum <= 5
    一个先排序,再筛选。
    select * from scott.emp e where rownum <= 5 order by e.sal desc
    另一个先筛选,再排序。

order by +rownum使用的时候如果order by后面的字段是主键和非主键结果不一样
如果order by主键的话先排序再取前几条记录 如果是非主键先取前几条记录再order by

  • 子查询
    若子查询未返回任何行,则住查询也不会返回任何结果
    (空值)select * from emp where sal>(select sal from emp where empno=8888);
    如果子查询返回单行结果,则为单行子查询,可以在主查询中对其使用相应的单行记录比较运算符
    (正常)select * from emp where sal>(select sal from emp where empno=7566);
    如果子查询返回多行结果,则为多行子查询,此时不允许对其使用单行记录比较运算符
    (多值)select * from where sal>(select avg(sal) from emp group by deptno);//非法

  • 内连接和外连接的区别
    内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现
    外连接: 包括
    (1)左外连接(左边的表不加限制)
    (2)右外连接(右边的表不加限制)
    (3)全外连接(左右两表都不加限制)

  • as用法
    as用于取别名,但是不用于给字段区别名,能用as的时候尽量用as,能够增强代码可读性

  • w,g,h,o顺序问题
    SELECT 语句选FROM,再WHERE,再GROUP,再HAVING,再SELECT,再ORDER,别名是SELECT指定的,不能使用

  • 分组函数
    COUNT() 返回查寻的行数
    MAX() 返回表达式的最大值
    MIN() 返回表达式的最小值
    SUM() 返回表达式的总合
    AVG() 返回表达式的平均值
    分组函数,不能和distinct合用,实际上分组函数已经起了distinct的作用,如要同时使用必须添加group by
    分组函数通常是要和group by一起使用
    有group by 的时候 select 后面只能包含 group by后面的字段

  • 在同一张表中用一个字段限制(非极值限制,极值限制用子查询)另一个字段的展示
    DB基础_第2张图片

  • 要查询的字段如果用了分组函数,则所有的字段都要使用分组函数,若有的没有,则需要用w(where)g(group by)h(having)o(order by)之类补齐

  • alter
    –增加字段 alter table tablename add column fieldname varchar2(2)
    或者 alter table tablename add(fieldname clob)
    – 删除字段 alter table tablename drop column fieldname
    – 修改字段 (修改字段名字) alter table tablename rename column oldfield to newfield(修改字段大小) alter table tablename modify fieldname varchar2(2000)

  • 函数
    1.字符串函数
    ||连接符
    upper()
    lower()
    length()
    initcap()首字母大写
    concat()
    substr()
    replace()
    instr()查询子字符串在母字符串中的位置
    lpad()在母字符左侧串中插入子字符串
    rpad()在母字符右侧串中插入子字符串
    trim()
    fm取出前后空格,用法后面直接跟日期fmyyyy表示取年份,fmmm表示取月份,fmdd表示取日,yyyy,mm,dd不能换其他写法,如不能写成yy,m,d等等
    2.数值函数
    round()
    mod()
    trunc()截取字符串
    3.日期函数
    months_between()时间a和时间b之间相差的月份数
    add_months()在指定时间基础上加上n个月份
    next_day()下一个指定时间出现在什么时候
    last_day()指定时间当月的最后一天
    4.转换函数
    to_char()
    to_number()
    to_date()
    5.通用函数
    nvl(exp,指定值)如果指定字段为空显示指定值,其余不变
    nvl2(exp,指定值1,指定值2)如果指定字段为空显示指定值1,其余显示指定值2
    nullif(exp1,exp2)如果exp1和exp2相等则返回空(NULL),否则返回第一个值
    coalesce()语法为COALESCE(表达式1,表达式2,…,表达式n),n>=2,此表达式的功能为返回第一个不为空的表达式,如果都为空则返回空值。
    case()函数
    CASE sex
    WHEN ‘1’ THEN ‘男’
    WHEN ‘2’ THEN ‘女’
    ELSE ‘其他’ END
    decode()函数

  • dual表用法
    获取当前用户名
    获取系统时间
    计算器
    得到序列的下一个值或当前值,用下面语句
    select your_sequence.nextval from dual;–获得序列your_sequence的下一个值
    select your_sequence.currval from dual;–获得序列your_sequence的当前值

  • merge用法
    merge into是对比插入/更新
    一般是增量整合全量做

merge into products p using (select * from newproducts) np on (p.product_id = np.product_id) when matched then update set p.product_name = np.product_name when not matched then insert values(np.product_id, np.product_name, np.category)

oracle中merge的用法

  • DB基础_第3张图片

  • insert,update,delete都有可能产生事务,select不会产生事务。事务是为了保证数据的完整性,通常出现在对多张表的操作,单表操作一般不需要添加事物。在查询的时候使用缓存可以大大减少游标的使用量,select * from a where a.id=?使用类似的语句可以大大减少游标使用量,因为在数据库中只执行了一条select语句,如果每条查询都使用select对于高并发查询,会出现游标不够的情况,在极端情况下可能会导致服务器宕机。

  • with yy as(
    select kk.* from(
    (select * from a)

    union all

    select * from b tt
    left join c tt1
    where a.ddlx is not null
    order by a.description
    )kk
    )

select * from yy

  • 注意点:查询数量限制select * from (select rownum as num, t* from insurance_type t) where num >= 100;
    select *
    from (select rownum as num, t.*
    from (select t1.user_code,
    t1.username,
    t1.name,
    t3.insurance_type_code,
    t3.insurance_type_name,
    t4.description
    from ta_survey_provide t1,
    ta_survey_vs_insure t2,
    ta_insurance_type t3,
    ta_org_info t4
    where t1.id = t2.survey_id
    and t2.insurance_type_id = t3.id
    and t1.org_id = t4.id
    and t1.survey_type = 2
    and t2.insurance_type_id is not null) t)
    where num > 180000 and num <= 240000;

  • 注意点:嵌套select(本条sql语句出错原因在最后的order by,因为句首使用了distinct,所以如果使用未出现的字段进行order by排序的话,必须要加表名,这也体现了distinct的特性)
    select
    from
    (
    select
    distinct t4.USER_CODE,
    to_char(t2.DISPATCH_TIME, ‘yyyy-mm-dd’) DISPATCH_TIME,
    (
    case when (sysdate - t2.dispatch_time) * 24 * 60 > 5 then 1 else 0 end
    ) as FLAG,
    t1.REGIST_NO,
    decode(t1.LOSS_NO, ‘0’, ‘0’, ‘1’) as LOSS_NO,
    t1.LOSS_TYPE,
    t5.DESCRIPTION,
    t4.NAME,
    t2.YARDMAN_NUMBER,
    t2.YARDMAN_NAME,
    t2.DISPATCH_TYPE,
    t2.SURVEY_PLACE,
    t1.STATUS,
    t1.CONTACT,
    t1.REMARK
    from
    ta_loss_item t1,
    ta_dispatch_item t2,
    ta_case_info t3,
    ta_survey_provide t4,
    ta_org_info t5
    where
    t1.id = t2.loss_id
    and t3.id = t1.case_info_id
    and t4.user_code = decode(
    t2.dispatch_type, 2, t2.video_survey_number,
    1, t2.survey_number, t2.survey_number
    )
    and t4.org_id = t5.id
    and t1.status = 2
    and t2.DISPATCH_TIME >= to_date(‘2015-12-20’, ‘yyyy-mm-dd’)
    and t2.DISPATCH_TIME <= to_date(‘2016-01-07’, ‘yyyy-mm-dd’)
    )
    order by
    dispatch_time desc

  • 注意点:oracle选择函数,decode函数
    select
    t2.dispatch_time,
    (case when (sysdate-t2.dispatch_time)*24*60>5 then 1 else 0 end) as flag,
    t1.regist_no,
    t1.loss_no,
    t1.loss_type,
    t5.description,
    t4.user_code,
    t4.name,
    t2.yardman_number,
    t2.yardman_name,
    t2.dispatch_type,
    t2.survey_place,
    t1.status,
    t1.contact,
    t1.remark
    from
    ta_loss_item t1,
    ta_dispatch_item t2,
    ta_case_info t3,
    ta_survey_provide t4,
    ta_org_info t5
    where
    t1.id = t2.loss_id
    and t3.id = t1.case_info_id
    and t4.user_code = decode(
    t2.dispatch_type, 2, t2.video_survey_number,
    1, t2.survey_number, t2.survey_number
    )
    and t4.org_id = t5.id
    and t1.status = 2
    and t2.dispatch_time >= to_date(
    ‘2015-12-31 10:10:10’, ‘yyyy-MM-dd hh24:mi:ss’
    )
    order by
    t2.dispatch_time desc

  • 三表查询
    select
    g.main_image_ufid,
    g.main_name,
    i.goods_name,
    i.buy_number,
    i.sale_price,
    o.amount,
    o.order_no,
    o.status
    from orders o, order_items i
    left join goods g
    on g.id=i.goods_id
    where i.order_id =o.id

  • select from [where] [group by] [having] [order by]
    多表查询count
    select
    (select count(1) from tc_rl_grbsb)tc_rl_grbsb,
    (select count(1) from tc_rl_jyrl)tc_rl_jyrl
    truncate table 表名:删除对应的表,且主键从零开始
    oracle 关于to_number()

    1. 将表中的某个字段从物理存储上的字符型转换为物理存储上的数字型,
      没有快捷的直接的方法,只能重建字段或表
    2. 可以在表上建立视图, 这是在大系统中很常用的方法
    3. 一般直接查询时可以 select to_number(varchr_field) form tab 得到结果
    4. 注意: 尝试将英文字符用to_number转换为数字都会提示出错.
      INSTR (源字符串,目标字符串, 起始位置, 匹配序号) //匹配序号:第几次出现在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置。只检索一次,就是说从字符的开始到字符的结尾就结束。
      语法如下:
        instr( string1, string2 [, start_position [,nth_appearance ] ] )
        参数分析:
        string1
        源字符串,要在此字符串中查找。
        string2
        要在string1中查找的字符串.
        start_position
      代表string1 的哪个位置开始查找。此参数可选,如果省略默认为1. 字符串索引从1开始。如果此参数为正,从左到右开始检索,如果此参数为负,从右到左检索,返回要查找的字符串在源字符串中的开始索引。 nth_appearance 代表要查找第几次出现的string2. 此参数可选,如果省略,默认为 1.如果为负数系统会报错。
        注意:
        如果String2在String1中没有找到,instr函数返回0.
        示例:
        SELECT instr(‘syranmo’,’s’) FROM dual; – 返回 1
        SELECT instr(‘syranmo’,’ra’) FROM dual; – 返回 3
        SELECT instr(‘syran mo’,’a’,1,2) FROM dual; – 返回 0
        (根据条件,由于a只出现一次,第四个参数2,就是说第2次出现a的位置,显然第2次是没有再出现了,所以结果返回0。注意空格也算一个字符!)
        SELECT instr(‘syranmo’,’an’,-1,1) FROM dual; – 返回 4
        (就算是由右到左数,索引的位置还是要看‘an’的左边第一个字母的位置,所以这里返回4)
        SELECT instr(‘abc’,’d’) FROM dual; – 返回 0
        注:也可利用此函数来检查String1中是否包含String2,如果返回0表示不包含,否则表示包含。
        对于上面说到的,我们可以这样运用instr函数。请看下面示例:
        如果我有一份资料,上面都是一些员工的工号(字段:CODE),可是我现在要查询出他们的所有员工情况,例如名字,部门,职业等等,这里举例是两个员工,工号分别是’A10001′,’A10002′,其中假设staff是员工表,那正常的做法就如下:

        SELECT code , name , dept, occupation FROM staffWHERE code IN (‘A10001’,’A10002’);

        或者:

        SELECT code , name , dept, occupation FROM staffWHERE code = ‘A10001’ OR code = ‘A10002’;

        有时候员工比较多,我们对于那个’觉得比较麻烦,于是就想,可以一次性导出来么?这时候你就可以用instr函数,如下:

        SELECT code , name , dept, occupation FROM staffWHERE instr(‘A10001,A10002’,code)>0;

        查询出来结果一样,这样前后只用到两次单引号,相对方便点。

        还有一个用法,如下:

        SELECT code, name, dept, occupation FROM staff WHEREinstr(code, ‘001’) > 0;
        等同于
        SELECT code, name, dept, occupation FROM staff WHEREcode LIKE ‘%001%’ ;

Oracle的instr函数使用实例

INSTR方法的格式为
INSTR(src, subStr,startIndex, count)
src: 源字符串
subStr : 要查找的子串
startIndex : 从第几个字符开始。负数表示从右往左查找。
count: 要找到第几个匹配的序号
返回值: 子串在字符串中的位置,第1个为1;不存在为0. (特别注意:如果src为空字符串,返回值为null)。

用法举例:

最简单的一种,查找l字符,首个l位于第3个位置。
SQL> select instr(‘hello,java world’, ‘l’) from dual;

INSTR(‘HELLO,JAVAWORLD’,’L’)

3

查找l字符,从第4个位置开始。
SQL> select instr(‘hello,java world’, ‘l’, 4) from dual;

INSTR(‘HELLO,JAVAWORLD’,’L’,4)

4

查找l字符,从第1个位置开始的第3个
SQL> select instr(‘hello,java world’, ‘l’, 1, 3) from dual;

INSTR(‘HELLO,JAVAWORLD’,’L’,1,

15

查找l字符,从右边第1个位置开始,从右往左查找第3个(也即是从左到右的第1个)
SQL> select instr(‘hello,java world’, ‘l’, -1, 3) from dual;

INSTR(‘HELLO,JAVAWORLD’,’L’,-1

3
找不到返回0
SQL> select instr(‘hello,java world’, ‘MM’) from dual;

INSTR(‘HELLO,JAVAWORLD’,’MM’)

0

源字符为空字符串”的情况
复制代码代码如下:

– Created on 2010-12-22 by CHEN
declare
– Local variables here
i varchar2(2);
begin
– Test statements here
i := instr(”,’,’);
if i is null then
dbms_output.put_line(’ i is empty’);
end if;
end;
结果输出:
i is empty
Oracle SQL语句大全
1.desc(描述 emp 描述emp这张表
2.desc dept 部门表
3.desc salgrade 薪水等级
4.select *from table 查找表中的元素
5.dual 是系统中的一张空表
6.select *from dual
7.select sysdate from dual 取出系统时间
8.select ename,sal*12 “annulsal”(取的别名 fromemp; 查找用户姓名和用户的年薪
9.任何含有空值的数学表达式的值都是空值
select ename,sal*12+comm from emp;
10.select ename||sal from emp 其中的||相当于将sal全部转化为字符串
11.表示字符串的方法
select ename ||’ajjf’ from emp;
12.如果其中有一个单引号就用2个单引号来代替他
select ename||’sakj’ ‘lds’from emp;
13.select distinct deptno from emp (去除部门字段中重复的部分,关键字distinct)
14.select distinct deptno,job from emp;(去除这2个字段中重复的组合)
15.select *from dept where deptno=10; 取出条件(取出部门编号为10的记录)
16.select * from emp where ename=’CLIRK’; 取出部门中姓名为clirk的记录(注意取出过程中
ename用单引号隔开)
17.select ename,sal from emp wheresal>1500; 取出部门中薪水大于1500的人的姓名
18.select ename,sal,deptno from emp wheredeptno<> 10 取出部门中的部门号不等于10的
19.select ename,sal,deptno from emp whereename>’CBA’ 取出部门中员工名字大于CBA的员
工(实际比较的是ACIIS码)
20.select ename,sal from emp where salbetween 800 and 1500
select ename,sal from emp where sal>=800 and sal<=1500; (取出800和1500之间的数)
21.select ename,sal,comm from emp wherecomm is null (选出其中的空值)
select enmae,sal,comm from emp where comm is not null(选出其中的非空值)
22.select ename,sal,comm from emp where salin (800,1500,2000);取出这3者之中的
select ename,sal,comm from emp where ename in(‘simth’);
23.select ename,sal,hiredate from emp wherehiredata>’3-04月-81’;宣传符合条件的日期
24.select ename,sal,from emp wheresal>1000 or deptno=10; 找出工资薪水大于1000或者
部门号等于10的员工
25.select ename,sal from emp where sal notin(500,1000); 查找薪水不在500到1000的员
工姓名和月薪
26.select ename,sal from emp where enamelike ‘%ALL%’;
select ename,sal from emp where ename like ‘_%A%’; 查找姓名中含有ALL的客户
信息一个横线代表一个通配符
27.select ename,sal from emp where enamelike ‘_% ’; 自己指定转易字符
select ename,sal from emp where ename like ‘_%\%%’; 查找中间含有%相匹配
的客户信息运用转易字符
28.select * from dept order by deptno 对表中元素按部门号排序 select *from dept order by deptno desc 默认为升序可以用desc
按降序
29.select ename,sal from emp where sal<>1000 order by sal desc 按照查询条件来查询并排
序asc升序排列
30.select ename,sal*12 from emp where enamenot like ‘_%A%’ and sal>800 order by sal desc
31.select lower(ename) from emp 将ename都转化为小写 lower是函数能将字母转化为小

32.select ename from emp where lower(ename)like ‘_%a%’; 找出ename 中所有的含有a的字符
33.select substr(ename,2,3) form emp 从第2个字符开始截取3个字符
34.select chr(65) from dual; 将65转化为字符
35.select ascii(‘A’) from dual 将ACSII码转化为字符串
36.select round(23.565)from dual 四舍五入
36.select round(23,4565,2)from dual 四舍五入到第二位
37.select to_char(sal,’ 99.999.9999)fromempselecttochar(sal,L99,999,9999)formempL38.selecthiredatefromempselecttochar(hiredate,YYYYMMDDHH:MI:SS)fromemp;selecttochar(sysdate,YYYYMMDDHH:MI:ss)fromdual;selecttochar(sysdate,YYYYMMDDHH24:MI:SS)fromdual39.selectename,hiredatefromempwherehiredate>todate(20052312:32:23,YYYYMMDDHH:MI:SS);40selectsalfromempwheresal>tonumber( 1,250.00','$9,999.99’); 取出比它大的一切字符串
把特定格式的数字转化成字符
41 select ename,sal+nvl(comm,0) fromemp; 讲comm值为空的用0来替换单行函数以
一条记录为条件一条对一条
42.select Max(sal) from emp;
select Min(sal) from emp;
select avg(sal) from emp;
select sum(sal) from emp;
select count(*) from emp; 查看表中一共有多少条记录
select count(*) from emp where deptno=10; 查找部门10一共有多少人
43.select avg(sal),deptno from emp group bydeptno; 按部门号进行分组
select deptno,job,max(sal) from emp group by job,deptno; 按工作和部门号进行分组
44.select ename from emp where sal=(selectmax(sal) from emp); 子查询查找部门中薪水最高
的员工姓名
45.group by 注意出现在select列表中的字段如果没有出现在组函数中必须出现在group by
子句中
46.select avg(sal),deptno from emp group bydeptno having avg(sal)>2000; 选出部门中平均
薪水大于2000的部门
47.select * from emp where sal>100 groupby deptno having ……….order by……..
先取数据–过滤数据——分组—-对分组限制——-排序
48.select avg(sal) from emp wheresal>2000 group by deptno having avg(sal)>1500 order by avg(sal) desc;
查找部门中平均薪水打印2000的员工并按部门号进行排序查询分组后的平均薪水必须大
于1500查询结果按平均薪水从低到高排列
49.select ename from emp wheresal>(select avg(sal) from emp);
查找出员工中薪水位于部门平均薪水之上的所有员工
50.select ename,sal from emp join(selectmax(sal) max_sal from emp group by deptno) t
on(emp.sal=t,max_sal andemp.deptno=t.deptno);
查找每个部门中薪水最高的
51.select e1.ename,e2.ename from emp e1,empe2 where e1.mgr=e2.empno; 表的自
连接
52.select dname,ename from emp cross joindept 交叉连接笛卡尔
SQL99中的新语法
53.select ename,dname from emp join depton(emp.deptno=dept.deptno);
54.select ename,dname from emp join deptusing(deptno); 查找emp和dept表中
deptno相同的部分。
55.select ename,dname,grade from emp e joindept d on(e.deptno=d.depno)
joinsalgrade s(e.sal between s.losal and s.hisal)
(三表查找
whereename not like ‘_%A%’;
56.select e1.ename,e2.ename from emp e1join emp e2 on(e1.mgr=e2.deptno); 表的自连接
57.select e1.ename,e2.ename from emp e1left join emp e2 on(e1.mgr=e2.deptno) 左外表连接
select ename,dname from emp e right join dept d on(e.deptno=d.deptno)右外连接
select ename,dname from emp e full join dept d on(e.deptno=d.deptno)全连接
58.求部门中薪水最高的
select ename,sal from emp join (select max(sal) max_sal, deptno from empgroup by deptno) t
on(emp.sal=t.max_sal and emp.deptno=t.deptno);
59.求部门中薪水等级的平均值
select deptno,avg(grade) from(select deptno,ename,grade,from emp joinsalgrade s on(emp.sal
between s.losal and s.hisal))t group bydeptno;
60.查找雇员中哪些是经理人
select ename from emp where empno in(select mgr from emp);
61.select distinct e1.sal from emp e1 joinemp e2 on(e1.sal

你可能感兴趣的:(oracle,数据库,优化)