oracle--

结构化查询语言:Structured Query Language

数据的持久化(保存数据)

DDL 化表头

create table

 (column name 列名)

 (data type 数据类型 length 长度)

 (constraint 约束 唯一且非空)

alter table 修改表结构

drop table

 

DML 填数据

    insert 插入数据,一行

    update 修改数据,某行的某列值/某些行的某列值/所有行的某列值

   delete 删除一行

TCL --TransactionControl Langage

  commit 提交

  rollback 回滚(刚才作的动作消除了相当于ctrl+z)

 

DQL --Data QueryLangage

  select 查询

  

DCL Data ControlLangage

  grant 授权

  revoke  收回授权

 

多用户系统

  权限

     例如:connect tarena/tarena

          create table account();

          grant select on account to jsd1303//给jsd1303看account表

          revoke select on account to jsd1303//不给jsd1303看account表      

       

          connect jsd1303/jsd1303

          select...from tarena.account

          select...form account(jsd1303里的account)

        

create database 创建数据库

 

DBA(database adminstrator) 数据库管理(ocp)

在平台(os)安装oracle软件  unix,linux

 

linux:sql developer

solaris:192.168.0.20 192.168.0.23192.168.0.26 //数据库的IP

 

连接数据库需要的信息 数据库的IP 端口号 数据库名 用户名 口令

 

查询表:源表

desc account

 

select 语句的查询结果:结果集

 

投影操作:结果是部分列

选择操作:结果是部分行

连接操作:结果集来自多张表

select real_name,idcard_no fromaccount

selectbase_cost,base_duration,unit_cost from cost

 

select 语句包含多个子句

select 子句 实现投影操作

from 子句 标名

 

sql 4GL  我要什么,rdbms 解放程序员

 

列别名适合计算字段,原名和别名之间可以使用as关键字

别名中包含空格 特殊字符或者希望大小写敏感,用“”

双引号表示标识名,列别名就是一个标识名

oracle中的‘s用'''s'表示,其中的两个‘’表示中文‘

 

desc account;

selectnvl(base_cost,0)+(250-nvl(base_duration,0))*nvl(unit_cost,0) fee_250 from cost;

selectnvl(base_cost,0)+(250-nvl(base_duration,0))*nvl(unit_cost,0) "Fee 250"from cost;

select * from cost;

select real_name ||'   '|| idcard_no client  from account;

select real_name||'''s IDCARD NOis '||idcard_no||'.' carddd from account;

select distinct unix_host fromservice;

 

select子句后面可以跟列名,*,表达式(算术,字符串),distinct

distinct 对结果集去重

where 子句后跟条件表达式

                 列名 常量

                 比较运算符

                 文字值

                 子句后不能跟列别名

session 会话

       select count(*) from v$session whereusername=‘JSD1303_1’;

       会话(session)查看jsd1303_1进行登录的人数

 

 

课外练习:

1 有哪些不同包在线时常 base_duration

2 理解连接过程

3 预习where子句



比较:

    select base_cost*12,base_duration*12 fromcost where base_cost*12=70.8;

    select base_duration*12 from cost wherebase_cost=70.8/12;//这个相对来说较好

 

执行顺序:from-->where-->select

where 不可跟列别名,后尽量不跟表达式

“”引起来的oracle表示标识符

     select unix_host from service where"OS_USERNAME"=“huangr“

     select unix_host from service whereos_username=“huangr“;其中"huangr"表示列名

不加‘’也表示标识符select unix_host from service where os_username=huangr;其中huangr表示列名

      select unix_host from service whereos_username=‘HUANGR’;//字符串不一样

 

upper(p1)大写  lower(p1)小写  initcap(p1)首字符大写

     select unix_host from service whereupper(os_username) = 'HUANGR';

     select unix_host from service wherelower(os_username) = 'huangr';

     select unix_host from service whereinitcap(os_username) = 'Huangr';

 

where 条件用and or连接,并且and优先级高于or

between..A1..and..B1.   ==[A1,B1]

多值运算的集合 in ()    =any()

    select base_cost from cost where base_costin(5.9,8.5,10.5);

    select base_cost , base_duration from costwhere base_cost = any(5.9,8.5,10.5);

 

in() 多值运算的集合

= 单值运算

=any() 多值运算的集合

 

null不等于0

null不等于空格

算术表达式中包含null结果为null

算术表达式中包含null需空值转换nvl

nvl()类型可以是number characterdate,参数类型必须一致

 

=精确比较

like 像....什么一样模糊匹配

    %表示0个任意多个字符

    _表示任意一个字符

   

通配符的转义: _的转义

         select os_username,unix_host fromservice where os_username like 'h\_%' escape '\';

is null:

       select base_cost,unit_cost from costwhere unit_cost is null;

 

不等于:<>     ^=     !=

 

is null -------------> isnot null

like--------------- >not like

between and ---------- > not between and

in-----------------> not in<============> <>and <>and<>  <>all

      select base_cost,unit_cost from costwhere base_cost <>5.9 and base_cost^=8.5 and base_cost!=10.5;

      not in()集合中包含null值,select语句执行结果为no rows selected

          select base_cost,unit_costfrom cost where base_cost not in(5.9,8.5,10.5) or base_cost is null;

      in()集合中包含null值,select语句执行结果和没有null都是一样的

          select base_cost,unit_cost from costwhere base_cost in (5.9,8.5,10.5) or base_cost is null;

 

asc升序     des降序

按照整张表的第二列排序:

        select base_cost,unit_cost from costorder by 2;

select 后面跟的2是常量

    select 2 from cost;

单行单列

    select 2*2 from dual;

 

select upper('abc') fromdual;//ABC

 

select sysdate from dual;//查时间

alter session set nls_date_format='yyyy-mm-ddhh24:mi:ss';//修改时间

 

drop table slf purge;

 

字符大小敏感,日期格式敏感

要一个日期值,to_date

处理一个date类型的值,为了获得时间信息,to_char

select create_date,os_usernamefrom service where to_char(create_date,'fmmm')='03';//加上fm表示去掉空格和前倒立

 

select to_number('ab','xx')fromdual; 16*10+11

 

number 可以定义宽度

date 一定不能定义宽度

archar2必须定义宽度

char 可以不定义宽度(缺省是1)

字符大小写敏感  varchar2对空格是敏感的

 

                                     

select * from account;

select * from cost;

select * from service;

 

selectreal_name,create_date,idcard_no,birthdate,telephone from account;

 

select base_cost,base_durationfrom cost where base_cost=5.9;

 

selectbase_cost*12,base_duration*12 ann_duration from cost where base_cost=5.9;

 

selectbase_cost*12,base_duration*12 from cost where base_cost*12=70.8;

 

select base_duration*12 from costwhere base_cost=70.8/12;

 

select unix_host from servicewhere os_username='huangr';

select unix_host from servicewhere upper(os_username) = 'HUANGR';

select unix_host from servicewhere lower(os_username) = 'huangr';

select unix_host from servicewhere "OS_USERNAME" = 'huangr';

select unix_host from servicewhere upper(os_username) = 'HUANGR';

select unix_host from servicewhere lower(os_username) = 'huangr';

select unix_host from servicewhere initcap(os_username) = 'Huangr';

select unix_host from servicewhere upper(os_username) = 'HUANGR';

select unix_host from servicewhere lower(os_username) = 'huangr';

 

select base_cost from cost wherebase_cost>=5 and base_cost<=10;

select base_cost from cost wherebase_cost between 5 and 10;

 

select base_cost from cost wherebase_cost = 5.9 or base_cost=8.5 or base_cost=10.5;

select base_cost from cost wherebase_cost in(5.9,8.5,10.5);

select base_cost , base_durationfrom cost where base_cost = any(5.9,8.5,10.5);

 

select os_username,unix_host fromservice where os_username like 'h%';

select os_username from service;

select os_username,unix_host fromservice where os_username like 'h\_%' escape '\';

 

select base_cost,unit_cost

from cost

where unit_cost is null;

 

select base_cost,unit_cost

from cost

where unit_cost is not null;

 

select base_cost,unit_cost fromcost

where nvl(base_cost,0) notin(5.9,8.5,10.5);

 

select base_cost,unit_cost fromcost

where base_cost <>5.9 andbase_cost^=8.5 and base_cost!=10.5;

 

select base_cost,unit_cost fromcost

where base_cost notin(5.9,8.5,10.5) or base_cost is null;

 

select base_cost,unit_cost fromcost

where base_cost in (5.9,8.5,10.5)

or base_cost is null;

 

select os_username,create_datefrom service order by create_date;

select os_username,create_date fromservice order by create_date desc;

select base_cost from cost orderby base_cost desc;

select base_cost*12,name fromcost order by base_cost*12 desc;

select base_cost,unit_cost fromcost order by 2;

 

select 2 from cost;

select 2*2 from dual;

select upper('abc') from dual;

 

select unix_host,create_date fromservice

order by unix_host,create_datedesc;

 

create table slfslf(c1 number,c2number(6),c3 number(4,3),c4 number(3,-3),c5 number(2,4));

insert into slfslf(c1,c2) values(15000,2222);

select * from slfslf;

 

insert into slfslf values(1,2222,2.222,333033.,0.0042);

insert into slfslf values(2,555555,5.666,3333,0.0099);

insert into slfslf values(2,555555,5.6666,3333,0.0099);

 

update slfslf set c3=9.999 wherec1=15000;

 

select round(base_cost/30,1),round(base_cost/30),

            trunc(base_cost/30),trunc(base_cost/30,1)

from cost;

 

select sysdate from dual;

alter session setnls_date_format='yyyy-mm-dd hh24:mi:ss';

 

select create_date from service;

 create table slf (c1 date);

insert into slf values('2008-05-23 14:22:21');

//insert into slfvalues(to_date('1-september-08','DD-MON-RR'));

insert into slf values(to_date('2008-01-01','yyyy-mm-dd'));

select * from slf;

select c1 from slf;

selectto_char(c1,'DD-MON-RR')from slf;

 

insert into slf values (to_date('200101 01','yyyy mm dd'));

select to_char(c1,'yyyy')fromslf;

 

insert into slfvalues(to_date('2008-08-08 08:08:08','yyyy-mm-dd hh24:mi:ss'));

select to_char(c1,'yyyy-mm-ddhh24:mi:ss')from slf;

insert into slfvalues('2013-10-12 03:40:20');

select to_char(c1,'yyyy-mm-ddhh:mi:ss')from slf;

select create_date,os_usernamefrom service where to_char(create_date,'fmmm')='3';

select to_number('ab','xx')fromdual;

 

selectbase_cost,nvl(to_char(unit_cost),'no unit cost') from cost;


列出基础资费

select base_cost,nvl(to_char(unit_cost),'nonuit cost')from cost;

 

列出昨天今天和明天

alter session set nls_date_format='yyyy mm dd hh24:mi:ss';

selectsysdate-1,sysdate,sysdate+1 from dual;

select sysdate,sysdate+1/144 fromdual;

 

列出主机,用户名,以及开通的多长时间,并按照开通时间排序

select unix_host,os_username,create_date,round(sysdate-create_date)days

from service order by 4 desc;

 

//设置日期格式此是默认的

alter session setnls_date_format='DD-MON-RR';

 

alter session setnls_language='AMERICAN';

 

半年后

select add_months('01-JAN-08',6)from dual;

 

输出星期几(字符格式)

select to_char(sysdate,'DAY')from dual;

 

输出95-9-8的下个星期五

selectnext_day('08-SEP-95','FRIDAY') from dual;

 

输出当月的最后一天

select last_day(sysdate)fromdual;

 

alter session set nls_territory =america;

select add_months(sysdate,-1)from dual;//上个月

select add_months(sysdate,1) fromdual;//下个月

select last_day(sysdate) fromdual;//最后一天

selectto_char(last_day(sysdate),'DAY')from dual;//星期几

 

//base_duration 为20时unit_cost加0.05,base_duration为40时unit_cost加0.03

方法1

select case when base_duration =20 then unit_cost + 0.05

            when base_duration = 40 thenunit_cost + 0.03

            else unit_cost

            endnew_unit_cost,base_duration,unit_cost

            from cost;

方法2

selectdecode(base_duration,20,unit_cost+0.05,

                            40,unit_cost+0.03,

                            unit_cost)

                           new_unit_cost,base_duration,unit_cost

                            from cost;          

 

 

函数

单行函数

 数据函数 number varchar2 char date

 数值函数 round trunc

 字符函数 upper lower initcap length trim

 日期函数 add_months months_between last_day

 转换函数 to_date to_char to_number

 一般函数 nvl decode

表达式     case when

环境设置   session

 

NetCTOSS 报表

avg       平均值        number

sum       求和          number

count     计数         

max       最大值        number

min       最小值        number

 

组函数的返回值

1 所有的非空值的处理,返回值不为null

2 处理值都为null,count为0,其他都为null

 

语法顺序

select from where group by havingorder by

执行顺序

from where group byhaving select order by

select(对数据处理)

from(数据源:表)

where(选择操作:过滤行记录)

group by(分组)

having(过滤组记录)

order by(排序对象,select)

 

 

1.  当月包在线时长为20小时,单位费用涨5分,为40小时涨3分,其他不变(用UNION ALL实现)

select case when base_durationbetween 20 and 40

            then unit_cost+0.05

            when base_duration >40

            then unit_cost+0.03

            else unit_cost

            endnew_unit_cost,unit_cost,base_duration

from cost;

 

2 月包在线时长在40到100之间,月固定费用涨5角,月包在线时长大约100小时,月固定费用涨3角,其余不变

select case when base_durationbetween 40 and 100

            then base_cost + 0.05

            when base_duration<40

            then base_cost

            else

              base_cost+0.03

            endnew_base_cost,unit_cost,base_cost,base_duration

from cost;

 

3 huangrong的推荐人

select real_name, idcard_no

from account

where id in(select recommender_id

            from account

            where real_name='huangrong');

 

4 huangrong推荐了谁

select real_name,idcard_no

from account

where recommender_id in(select id

                        from account

                        wherereal_name='huangrong');

 

5   那些客户推荐了新客户又被老客户推荐

select real_name,idcard_no

from account

where recommender_id is not null

and id in (select recommender_id

           from account);

 

6 哪些用户没被推荐,也没推荐别人

select real_name,idcard_no

from account

where recommender_id is null

and id not in(selectnvl(recommender_id,0)

           from account);

 

7 那些os帐号的开通天数比同一台上unix服务器上的平均开通天数长

selectunix_host,os_username,create_date

from service o

whereround(sysdate-create_date)>(select round(avg(sysdate-create_date))

                                  from servicei

                                  wherei.unix_host=o.unix_host);

关联子查询:

子查询引用主查询的列

 

8 哪些客户是推荐人

select real_name,idcard_no

from account o

where exists (select 1 fromaccount i

              where o.id=i.recommender_id);

 

9 哪些客户开通了远程登录业务

select real_name,idcard_no

from account

where exists(select 1 fromservice

             whereaccount.id=service.account_id);

 

10    哪些客户没有申请远程登录业务

select real_name,idcard_no

from account

where not exists(select 1 fromservice

             whereaccount.id=service.account_id);

 

11  哪些客户不是推荐人

select real_name,idcard_no

from account o

where not exists(select 1 fromaccount i

                 where o.id=i.recommender_id);

 

 

子查询:

         非关联子查询 in,not in:

                      单列子查询

                       多列子查询(多列同时比较)

        关联子查询  exists,not exists

 

主属性:记录的唯一标识 id 约束 主键

idunix_host,os_username,,,account_id real_name,idno

非主属性 account_id 和real_name

real_name依赖account_id

 

组合问题

    select tabname1.colname1,tabname2.colname2

    from tabname1 join tabname2

    on tabname1.colname2=val1

    and tabname1.colname1=tabname2.colname2;

 

from on(过滤 表)joinon(内连接)select

from(t1 t2)-->t1表过滤-->过滤后的结果集跟t2内连接

 

     哪些客户在unix服务器上申请了远程登录

selecta.real_name,a.id,s.account_id,s.os_username

from account a cross join services

where a.id=s.account_id;

 

     哪些客户在unix服务器上申请了远程登录

selectaccount.real_name,service.account_id

from account join service

on account.id=service.account_id;

 

     客户huangrong在那些unix服务器上申请了远程登录

selecta.id,a.real_name,s.unix_host

from account a join service s

on a.real_name='huangrong'

and a.id=s.account_id;

            

     列出客户姓名以及开通的远程登录的数量

selecta.real_name,count(s.os_username)

from account a join service s

on a.id=s.account_id

group by a.real_name;

先连接(记录数多),再分组,再计算

select a.real_name,s.cnt

from account a join(selectaccount_id ,count(*) cnt

                    from service group byaccount_id)s

on a.id=s.account_id;

先分组,再计算,结果集做内连接

先执行s,s和account 做内连接

 

     列出每台中比开通天数比平均开通天数大的

selecta.create_date,a.os_username,s.days

from service a join(selectunix_host,round(avg(sysdate-create_date))days

                    from service group byunix_host)s                   

on a.unix_host=s.unix_host 

and round(sysdate-a.create_date)> s.days;

 

     列出客户姓名以及他的推荐人

select a.id,a.real_namerecommendername,s.real_name

from account a join(selectreal_name,recommender_id

                    from account)s

on a.id=s.recommender_id;

 

select t1.real_name client,

    decode(t2.id,t1.id,'norecommender',t2.real_name) recommender

from account t1 join account t2

on nvl(t1.recommender_id,t1.id) =t2.id;

 

     哪些客户是推荐人      

select distinct t2.real_name

from account t1 join account t2

ont1.recommender_id=t2.id;


关联子查询

主表和子表之间建关联,两张表的列写成表达式=

account service a.id=s.account_id

service cost  s.cost_id=c.id

 

内连接

主表:驱动表

子表:匹配表

驱动表和匹配表建关联,两张表的列写成表达式=

两张不同表的记录关系      一对多

同一张表的记录关系      一对多(一个客户可以推荐多个客户)

同一张表的记录关系叫自连接

 

 

外连接

左外连接,右外连接

跟内连接的区别:

                 驱动表是固定的

                 驱动表的所有记录都在结果集里

from t1 lef  (outer)join t2  //t1是驱动表

on t1.c1=t2.c2

外连接的结果集:是内连接的结果集+t1表中不匹配的记录和一条null记录(按t2表的结构)的组合

 

from t1 right (outer) joint2  //t2是驱动表

on t1.c1=t2.c2

 

from t1 full join t2

on t1.c1=t2.c2

 

 

 

列出客户姓名以及推荐人

select t1.real_nameclient,t2.real_name recommender

from account t1 join account t2

onnvl(t1.recommender_id,t1.id)=t2.id;

列出客户姓名以及推荐人

select t1.real_name client,

decode(t2.id,t1.id,'Norecommender',t2.real_name) recommender

from account t1 join account t2

onnvl(t1.recommender_id,t1.id)=t2.id;

 

select t1.id,t1.real_nameclient,nvl(t2.real_name,'No recommender') recommender

from account t1 left join accountt2

on t1.recommender_id = t2.id;

 

列出顾客开通那些远程登录

selecta.id,a.real_name,s.unix_host

from account a left join services

on a.id=s.account_id;

 

列出顾客开通那些远程登录

select a.id,a.real_name,s.*

from account a left join services

on a.id=s.account_id;

 

列出每个顾客都开通了多少远程登录(count跟匹配表里的非空列)

select max(a.id),max(a.real_name),count(s.cost_id)

from account a left join services

on a.id=s.account_id

group by a.id;//groupby 后跟驱动表中的列

 

select a.real_name,nvl(s.cnt,0)

from account a left join(selectaccount_id ,count(id) cnt

                        from service

                        group by account_id)s

on a.id=s.account_id;//效率高

left join所有的客户(申请业务的客户+没有申请业务的客户)

目的:降低表连接的数据量

 

那些人不是推荐人

select t1.real_name,t2.real_name

from account t1 left join accountt2

on t1.id =t2.recommender_id

where t2.id is null;

 

from t1 left join t2

on t1.c1=t2.c2

and t2.c3=''

在外连接之前对匹配表作过滤

from t1 t2 -->对t2过滤-->外连接

对匹配表的过滤弱项发生在连接之前,用on过滤

 

from t1 left join t2

on t1.c1=t2.c2

where t2.c1 is null

from t1 t2-->外连接-->where通过t2的列对外连接的结果集过滤

 

对驱动表的过滤必须用where子句实现

 

内连接解决问题:

             匹配

 

外连接解决问题:

             1 . 匹配问题+不匹配问题(一个都不能少)

             2. 不匹配问题(outer join+where匹配表.非空列 is null)-->not in,not exists

 

外连接的执行顺序

先将表进行外连接错作,再外连接的结果集用where子句进行过滤,最后用select 声称结果

 

哪些服务器上没有os帐号weixb

select h.id,s.os_username

from host h left join service s

on h.id=s.unix_host

and s.os_username='weixb'

where s.os_username is null;

 

select h.id,s.os_username

from host h left join(selectunix_host,os_username

                      from service)s

on h.id=s.unix_host

and s.os_username='weixb'

where s.os_username is null;

 

列出那个人属于那个年龄段

selecta.id,a.real_name,round((sysdate-a.birthdate)/365),s.name

from account a join age_segment s

onround((sysdate-a.birthdate)/365) between s.lowage and s.hiage;

 

huangrong的年龄段

selecta.id,a.real_name,round((sysdate-a.birthdate)/365),s.name,s.lowage,s.hiage

from account a join age_segment s

onround((sysdate-a.birthdate)/365) between s.lowage and s.hiage

where a.real_name='huangrong';

 

列出每个年龄段有多少客户

selectmax(s.name),count(a.real_name)

from  age_segment s left join account a

on round((sysdate-a.birthdate)/365)between s.lowage and s.hiage

group by s.id;

 

各类连接的应用场合

交叉连接(cross join)

         笛卡尔积

内连接(inner join)

         解决匹配问题

        1  等值连接   =

        2  非等值连接 >   <

        3  自连接

外连接(outer join)

         解决不匹配问题

         表的所有记录出现在结果集

 

集合

union/union all  并集(去重)/并集(不去重)

intersect  交集 (不重复)

minus   集合1-集合2

 

当月保在线时常为20小时单位费用涨5分,为40小时单位费用涨3分,其他不变

selectbase_duration,unit_cost+0.05

from cost

where base_duration=20

union all

selectbase_duration,unit_cost+0.03

from cost

where base_duration=40

union all

select base_duration,unit_cost

from cost

where base_duration not in(20,40)

or base_duration is null;

 

列出客户姓名以及推荐人(包含所有的客户)

select t2.real_name ,t1.real_namerecommender

from account t1 join account t2

on t1.id=t2.recommender_id

union all

select real_name,'no recommender'

from account

where recommender_id is null;

 

 

列出‘sun280’和'sun-server'用了那些相同的资费

select s.cost_id

from host h join service s

on h.id=s.unix_host

and h.name='sun280'

intersect

select s.cost_id

from host h join service s

on h.id=s.unix_host

and h.name='sun-server';

 

那些服务器上没有开通远程登录

select id

from host

minus

select h.id

from host h join service s

on h.id =s.unix_host

group by h.id;

 

找出第一列

select rownum,real_name

from account where rownum=1;

 

select rownum,real_name

from account

where rownum between 1 and 5;

rownum只能找从1开始的数据

 

找出4-6条记录

方法1:

select rownum,real_name fromaccount where rownum<=6

minus

select rownum,real_name fromaccount where rownum<=3;

方法2:

select real_name

from (select rownum rm,real_name

      from account where rownum <= 6) t

where t.rm>=4;

 

最早开通netctoss系统的前三个客户

selectreal_name,create_date,rownum

from (select real_name,create_date

      from account order by create_date)

where rownum <=3;



第4到第6位开通的用户

select rm,real_name,create_date

from (select rownum rm,real_name,create_date

      from account

      order by create_date)s

where rm between 4 and 6;

         

pl/sql课程

jdbc

service_detail具体登录信息,详单

pl/sql项目课程 计费月出帐

 

列出每个客户申请了那些资费政策

方法1

select ss.id,ss.real_name,ss.cost_id,c.name

from cost c join(selectc.id,c.real_name,a.cost_id

                 from account c join(selectaccount_id,cost_id,unix_host

                                     fromservice)a

                 on a.account_id=c.id)ss

on c.id=ss.cost_id;

方法2

select a.real_name,c.name

from account a join service s

on a.id=s.account_id

join cost c

on c.id=s.cost_id

 

create table sfl(

c1 number constraint sfl_c1_pkprimary key,

c2 number);

insert into sfl values(1,1);

insert into sfl values(1,1);//uniqueconstraint (JSD1303_1.SFL_C1_PK) violated错误  用户.约束名(JSD1303_1.SFL_C1_PK)

 

主键约束:primary key

        必须唯一并且不为空

        列级约束:create table sfl(

           c1 number constraint sfl_c1_pkprimary key,

           c2 number);

        表级约束:create table sfl(

           c1 number(2),

           c2 number,

           constraint sfl_c1_pk primarykey(c1));

 

  create table stu_cou(

  sid number(4),

  cid number(2),

  constraint stu_cou_sidcid_pk primary key(sid,cid),

  score number(3));//联合约束

         给存在的表加约束

    alter table account add constraintaccount_id_pk primary key(id)

     

 

唯一键约束:unique key

       列名+数据类型+constraint 表名_列名_ukunique

       不允许重复

        可以插入多个null

  create table test(

  c1 number(3) constraint test_c1_pk primary key,

  c2 number(2),

  c3 number(4),

  constraint test_c3_uk unique(c2,c3));//c2和c3组合唯一

 

 

非空约束:not null

         列名+数据类型+not null

 

外键约束:references foreign key

    create table child(

    c1 number(3)constraint child_c1_pkprimarykey,

    c2 number(2) constraint child_c2_fk referencesparent(1));//表child中的c2列要从parent去取得

          被引用的表:父表parent   pk   

          定义外键的表:子表child  fk  可以重复

          保证一对多关系的实现

          在子表的一列上定义外键:外键列

          外键列要引用父表中的一列,要求这列唯一特性(pk,uk)

         1 先create parent table,被引用列必须保证唯一(pk,uk),再create child table,建fk列

         2 先insert into parenttable,再insert into child table

         3 先delete from child,再deletefrom parent

         4 先drop child tble,再dropparent table

 

  drop table parent cascade constraints purge;//删除父表和子表之间的外键联系,并且删除父表

  create table child1(

  c1 number primary key,

  c2 number references parent(c1)

  on delete cascade);//加on delete cascade 时可以直接用drop parentwhere c1=2,将父表和子表中对应的记录同时删除

  create table child2(

  c1 number primary key,

  c2 number references parent(c1)

  on delecte set null);//删除drop parent where c1=2,删除父表中的记录,并且将子表的c2=2的记录设置为c2=null

 

 

检查约束:check

           列名+数据类型+constraints+表名_列名_ckchect (表达式);

 

create table child(c1number(3)constraint child_c1_pk primarykey,

c2 number(2) constraintchild_c2_fk references parent(1));

 

create table stlt_cou(

             suid number,

             cuid number,

             constraint stlt_cou_suidcuid_pkprimary key(suid,cuid),

             score number);

 

create table childd(

c1 number(2) constraintchildd_c1_pk primary key,

c2 number(3) constraintchildd_c2_fk references parentt(c1));

 

 

多对多

增加一张中间表,两个fk,fk引用多对多的两张表。两个一对多,从而实现多对多

 

 

 

事物transaction

commit(提交)  --》TCL

transaction=dmls+commit/rollbanck

 

dmls

create table(ddl自动提交)

 

数据库中有很多session,每个session只有一个活动事物(未commit)

事物隔离级别




pk uk fk ck nn

1 列上多个约束

1 列定义在多个列上

 

1对多关系  pk、uk   fk   违反3范式

多对多关系 增加一张表,定义2个fk,违反2范式

分开:没有数据冗余,没有数据不一致,dml的负担,数据记录很纯粹,select 作join操作,规范化

 

合表:dml负担重,select简单,快,去规范化做法

 

         fk pk  pk

name      id   |id    name

zs        1     1      ls

 

sql脚本(放在跟数据库建立连接的本机上)

//创建 slf_account表

create table slf_account(

id number(9) ,

recommender_id number(9),

login_name varchar2(30) not null,

login_passwd varchar2(8) notnull,

status char(1) not null,

create_date date default sysdate,

pause_date date,

clost_date date,

real_name varchar2(20) not null,

idcard_no char(18) not null,

birthdate date,

gender char(1) not null,

occupation varchar2(50),

telephone varchar2(15) not null,

email varchar2(50),

mailaddress varchar2(50),

zipcode char(6),

qq varchar2(15),

last_login_time date,

last_login_ip varchar2(15),

constraint slf_account_id_pkprimary key(id),

constraintslf_account_recommender_id_fk foreign key(recommender_id) referencesslf_account(id),

constraint slf_account_status_ckcheck(status in(0,1,2)),

constraintslf_account_idcard_no_uk unique(idcard_no),

constraint slf_account_gender_ckcheck(gender in(0,1)));

 

//创建slf_cost表

create table slf_cost(

id number(4) ,

name varchar2(50) not null,

base_duration number(11),

base_cost number(7,2),

unit_cost number(7,4),

status char(1) not null,

descr varchar2(100),

creatime date default sysdate,

startime date,

constraint sl_cost_id_pk primarykey(id),

constraint sl_cost_statuscheck(status in (0,1)));

 

//创建slf_service表

create table slf_service(

id number(10),

account_id number(9) not null,

unix_host varchar2(15) not null,

os_username varchar2(8) not null,

login_passwd varchar2(8) notnull,

status char(1) not null,

create_date date default sysdate,

pause_date date,

close_date date,

cost_id number(4) not null,

constraint slf_service_id_pkprimary key(id),

constraintslf_service_account_id_fk foreign key(account_id)references slf_account(id),

constraintslf_service_host_username_uk unique(os_username,unix_host),

constraint slf_service_status_ckcheck (status in(0,1,2)),

constraint slf_service_cost_id_fkforeign key(cost_id) references slf_cost(id)

);

 

//创建slf_host表

create table slf_host(

id varchar2(15) primary key,

name varchar2(20) not null,

location varchar2(20)

);

 

//创建slf_service_detail表

create table slf_service_detail(

id number(11) ,

service_id number(10) not null,

client_host varchar2(15),

os_username varchar2(8),

pid number(11),

login_time date,

logout_time date,

duration number(20,9),

cost number(20,6),

constraintslf_service_detail_id_pk primary key(id),

constraintslf_service_detail_sid_fk foreign key(service_id)references slf_service(id)

);

         

//创建slf_fee_log表         

 create table slf_fee_log(

log_date date not null,

service_id number(10),

fee_month char(6),

descr varchar2(500)

);

 

//创建slf_month_duration表

create table slf_month_duration(

service_id number(10),

month_id char(6),

service_detail_id number(11),

sofar_duration number(11)

);        

                       

//创建slf_bill表     

create table slf_bill(

id number(11),

account_id number(9)not null,

bill_month char(6)not null,

cost number(13,2) not null,

payment_mode char(1),

pay_state char(1) default 0,

primary key(id),

foreign key(account_id)referencesslf_account(id),

check(payment_mode in(0,1,2,3)),

check(pay_state in(0,1))

);

 

//创建slf_bill_item表     

create table slf_bill_item(

item_id number(11),

bill_id number(11) not null,

service_id number(10) not null,

cost number(13,2),

primary key(item_id),

foreign key(bill_id)referencesslf_bill(id),

foreign key(service_id)referencesslf_service(id)

);

 

//创建slf_role_info表     

create table slf_role_info(

id number(11),

name varchar2(20)not null,

primary key(id)

);

 

INSERT INTO SLF_COST VALUES(1,'5.9元套餐',20,5.9,0.4,0,'5.9元20小时/月,超出部分0.4元/时',DEFAULT,NULL);

INSERT INTO SLF_COST VALUES(2,'6.9元套餐',40,6.9,0.3,0,'6.9元40小时/月,超出部分0.3元/时',DEFAULT,NULL);

INSERT INTO SLF_COST VALUES(3,'8.5元套餐',100,8.5,0.2,0,'8.5元100小时/月,超出部分0.2元/时',DEFAULT,NULL);

INSERT INTO SLF_COST VALUES(4,'10.5元套餐',200,10.5,0.1,0,'10.5元200小时/月,超出部分0.1元/时',DEFAULT,NULL);

INSERT INTO SLF_COST VALUES (5,'计时收费',null,null,0.5,0,'0.5元/时,不使用不收费',DEFAULT,NULL);

INSERT INTO SLF_COST VALUES (6,'包月',null,20,null,0,'每月20元,不限制使用时间',DEFAULT,NULL);

commit;

 

 

ALTER SESSION SET NLS_DATE_FORMAT= 'yyyy mm dd hh24:mi:ss';

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

     REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1005,NULL,'taiji001','256528',1,'200803 15','zhangsanfeng','19430225','410381194302256528',13669351234,1);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1010,NULL,'xl18z60','190613',1,'200901 10','guojing','19690319','330682196903190613',13338924567,0);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1011,1010,'dgbf70','270429',1,'200903 01','huangrong','19710827','330902197108270429',13637811357,0);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1015,1005,'mjjzh64','041115',1,'201003 12','zhangwuji','19890604','610121198906041115',13572952468,1);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1018,1011,'jmdxj00','010322',1,'201101 01','guofurong','199601010322','350581200201010322',18617832562,1);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1019,1011,'ljxj90','310346',1,'201202 01','luwushuang','19930731','320211199307310346',13186454984,0);

 

INSERT INTOSLF_ACCOUNT(ID,RECOMMENDER_ID,LOGIN_NAME,LOGIN_PASSWD,STATUS,CREATE_DATE,

REAL_NAME,BIRTHDATE,IDCARD_NO,TELEPHONE,GENDER)

VALUES(1020,NULL,'kxhxd20','012115',1,'201202 20','weixiaobao','20001001','321022200010012115',13953410078,1);

COMMIT;

select * from slf_account;

 

INSERT INTO SLF_HOST VALUES('192.168.0.26','sunv210','beijing');

INSERT INTO SLF_HOSTVALUES('192.168.0.20','sun-server','beijing');

INSERT INTO SLF_HOST VALUES('192.168.0.23','sun280','beijing');

INSERT INTO SLF_HOST VALUES('192.168.0.200','ultra10','beijing');

COMMIT;

 

INSERT INTO SLF_SERVICE VALUES(2001,1010,'192.168.0.26','guojing','guo1234',0,'2009 03 1010:00:00',null,null,1);

INSERT INTO SLF_SERVICE VALUES(2002,1011,'192.168.0.26','huangr','huang234',0,'2009 03 0115:30:05',null,null,1);

INSERT INTO SLF_SERVICE VALUES(2003,1011,'192.168.0.20','huangr','huang234',0,'2009 03 0115:30:10',null,null,3);

INSERT INTO SLF_SERVICE VALUES(2004,1011,'192.168.0.23','huangr','huang234',0,'2009 03 0115:30:15',null,null,6);

INSERT INTO SLF_SERVICE VALUES(2005,1019,'192.168.0.26','luwsh','luwu2345',0,'2012 02 10 23:50:55',null,null,4);

INSERT INTO SLF_SERVICE VALUES(2006,1019,'192.168.0.20','luwsh','luwu2345',0,'2012 02 10 00:00:00',null,null,5);

INSERT INTO SLF_SERVICE VALUES(2007,1020,'192.168.0.20','weixb','wei12345',0,'2012 02 1011:05:20',null,null,6);

INSERT INTO SLF_SERVICE VALUES(2008,1010,'192.168.0.20','guojing','guo09876',0,'2012 02 11 12:05:21',null,null,6);

COMMIT;

 

 

grant connect,resource tojsd1303;//给用户授角色

connect,resource是角色的名字

角色:一堆权限的集合

 

create role connect;

grant create table to connect;

grant create index to connect;

 

给用户授系统权限

grant create table to jsd1303

 

//删除主键约束

alter table test drop primary keycascade;

 

//显示表的所有约束以及约束名

select constraint_name,constraint_type

from user_constraints

where table_name='TEST';

 

 

非空改空

alter table test modify(c1 null);

 

空改非空,修改之前保证此列中所有记录不为空

alter table test modify(c1 notnull);

 

删除约束

alter table test drop constraintcon_name;

 

//查找slf_service表中的约束名

select constraint_name,constraint_type

from user_constraints

where table_name='SLF_SERVICE';

 

//查找slf_service表中的约束名以及对应的列名

selectconstraint_name,column_name

from user_cons_columns

where table_name='SLF_SERVICE';

 

 

service 每个unix服务器的telnet服务,在unix服务器上的注册信息

service_detail :每个os帐号登录登出信息,详细信息

关系:数量  几对几

             紧密程度  可以/必须

一个telnet服务可以包含多个详单信息

一条详单信息必须属于一个telnet服务

 

一个客户可以申请多个telnet服务,一个telnet服务可以有多条详单信息

一条详单信息必须属于一个telnet 服务,一个telnet 服务必须属于一个客户

account(id pk) service(idpk,account_id fk not null)

service(id pk) service_detail(idpk,service_id fk not null)

 

用户,权限  多对多

database object 数据库对象

table 表

synonym 同义词

create synonym account fortarena.account;

view  视图

index  索引

sequence   序列号

 

create table(子查询)

//建表

create table service_20

as

select * from service

where unix_host='192.168.0.23';

 

create table service_20

as

select unix_host,os_username fromservice

where unix_host='192.168.0.23';

 

create tableservice_20(unix_host,days)

as

selectunix_host,sysdate-create_date from service

where unix_host='192.168.0.23';

这样创建表的时候,只有非空约束可以代过来

 

创建一张表,表结构于account一致,没有数据

create table account_90slf

as

select * from account

where 1=2;

创建一张表,表结构于account一致,没有数据

create table account_90slf1

as

select * from account

where 1=1;

 

 account_90表中包含所有的90后客户

insert into account_90slf

select * from account

whereto_char(birthdate,'yyyy')between 1990 and 1999;

 

视图:

create table slf(c1 number,c2number);

insert into slf values(1,1);

insert into slf values(1,2);

insert into slf values(1,3);

insert into slf values(1,4);

 

create or replace view slf_v1

as

select * from slf

where c1=1;

select * from slf_v1;

 

在视图添加c1=1的记录的时候,slf也会添加记录

如果在视图添加c1!=1的记录的时候,会在slf中添加的而不是在视图中添加

 

view 和windows中的快捷方式相似

             试图在数据库中不存储数据值,即不占空间

             只在系统表中存储对视图的定义

             试图实际就是一条select语句

 

select text from user_views

where view_name='SLF_V1';

结果为:"select "C1","C2" from slfwhere c1=1"

 

inline-view内嵌视图

from (select c1 from slf)

 

heap table 堆表

partition table 分区表

 

每个客户选择了哪些资费标准

create or replace view acc_co

as

select a.real_name,c.name

from account a left join services

on a.id=s.account_id

left join cost c

on s.cost_id=c.id;

 

select a.real_name,c.name

from account a,service s,cost c

where a.id=s.account_id(+)

and s.cost_id=c.id(+);

 

  from t1,t2

  where t1.c1=t2.c2(+)   //(+)表示匹配表

==>from t1 left join t2   //t1是驱动表

  on t1.c1=t2.c2

 

哪个unix服务器上没有weixb这个os帐号

select distinct id

from host

minus

select unix_host

from service

where os_username='weixb';

 

select h.id,s.os_username

from host h,service s

where h.id=s.unix_host(+)

and s.os_username(+)='weixb' 外连接之前过滤

and s.id is null;  外连接之后过滤

 

简单视图

        基于单张表并且不包含函数或表达式的试图,可执行dml语句(即可实现增删改操作)

create or replace view acc_co

as

select * from account  where

复杂视图

        包含函数 表达式或者分组数据的视图,在该试图上执行dml语句时必须要符合特定条件

         在定义复杂视图时必须为函数或者表达式定义别名

create or replace view acc_co

as

select c1,count(*) cnt from

连接视图

         基于多个表建立的视图,一般来说不会在该视图上执行insertupdate delete操作

 

drop table slf,所有依赖该表的对象(view)全部失效

改变view的定义:create or replace view

改变view的状态:alter view view_name compile;

删除view:drop view view_name;

view status valid invalid

 

create or replace view slf_sl

as

select * from slf

where c1 = 1

with check option;//要求插入的数据必须符合where条件

 约束p u  c  r

with check option 约束vconstraint_type  v

with read only//约束o  只读视图,不允许操作

create or replace view slf_sl

as

select * from slf

where c1= 1

with read only;//只读约束

 

索引index

  create index 索引名 on 表名(列名);

  create index index_name on table_name(colname);

 

create database

物理角度:在os上建文件  数据文件(table)、日志文件(transation)、控制文件(数据文件和日志文件)       

 

delete from bigtable

1    表占用的空间不释放

2   保存旧数据到回滚段,时间长

3   数据可恢复(rollback)

 

truncate table ddl(删除所有记录)

1    释放表占用的空间

2   不会保存旧数据,时间短

3   数据不可恢复(ddl自动提交的)

 

全表扫描fts

     

通过rowid扫描

  rowid:标识一条记录的物理地址

         使用index比fts快-->快速找到rowid,排序-->降低读取data block数量

 

唯一性索引

create unique index indname ontabname(conname);

非唯一索引

 

单列索引

 

联合索引

create table test(c1 numberprimary key,c2 number,c3 number);

create index test_c2_c3_idx ontest(c2,c3);

哪些写法导致索引不可用

      1 like和substr

      2 where colname is null

      3 not in

                4      <>

序列:

create table ss(c1 number primarykey);

create sequence sllss start with1110001;

insert into ssvalues(sllss.nextval);

insert into ssvalues(sllss.nextval);

commit;

select * from ss;

insert into ssvalues(sllss.nextval);

rollback;

insert into ssvalues(sllss.nextval);

//结果:1110001   1110002  1110004

select sllss.currval from dual;

//结果:1110004

selectsequence_name,cache_size,last_number from user_sequences;

//结果

sequence_name       cache_size     last_number      

SLLSS                    20          1110021

S1                       20          1303021

S_ITEM_ID                20             1             

 


PL/SQL(Procedural Language/SQL)是程序

扩展

         变量和类型

          控制和结构

          过程与函数

PL/SQL块

         声明部分:DECLARE

          执行部分:BEGIN

          异常处理:EXCEPTION

    END

 

select 'Hello World' from dual;

       

打印“Hello World”

    begin

      dbms_output.put_line('Hello World');

end;//在服务器端打印

 

set serveroutput on;//设置在客户端打印

begin 

 dbms_output.put_line('Hello World');

end;

    //dbms_output package 包,包里包含过程、函数,过程put_line('Hello World')

          调用过程(过程本身没有返回值)

          调用函数(函数本身是有返回值)

 

c/s client/server sqlplus,sqldeveloper,jdbc/oracle server

b/s browseserver  b/AS/oracle server

 

注释符号:

         单行注释:--

          多行注释:/*     */

 

数据类型

         标量类型

                  数字型 number

            number的子类型dec(38),float(38),real(18)

            binary_integer(只能用于pl/sql)

                  字符型varchar2,varchar(长度:1...32767)

            string(只能用于pl/sql长度:1...32767)

            char(长度:1...32767)

            long

                  日期型

                  布尔型 boolean

                                 用于存储逻辑值(true,false,null)

                                  不能向数据库中插入boolean类型的数据

                                  不能将列值保存到boolean变量中

                                  只能对boolean变量执行逻辑操作

         复合类型

       record(记录类型),associativearray,nested table,varray

 

 变量声明

    var_name type[constant][not null][:=value];

    pl/sql规定没有初始化的变量为null

%type方式

               变量具有与数据库表中某列或其他变量相同的类型

      declare v_realname varchar2(20);

      declare v_realnameaccount.real_name%type;

 

定义变量,输出他们的值

set serveroutput on;

declare

 var_day date := sysdate;

 v_daychar varchar2(50);

begin

 v_daychar := to_char(var_day,'yyyy mm dd hh24:mi:ss');

 dbms_output.put_line('Current Time:'||v_daychar);

end;

 

 

if语句:

if then

end if;

 

if then

else

end if;

 

if then

elsif then

elsif then

else

end if;

 

//设置一个布尔类型的变量,真的时候显示'true',假的时候显示'false',否则显示空

declare

 t boolean := true;

begin

 if t = true then

     dbms_output.put_line('true');

 elseif t = false then

     dbms_output.put_line('false');

 else

     dbms_output.put_line('null');

 end if;

end;

 

loop循环语句:

    exit when 是必须的,否则无法停止

loop

  statement1;

  statement2;

  exit when

end loop;

 

while循环语句

             在while循环中仍可以使用exit或exit when子句

whileloop

  statement1;

  statement2;

end loop;

 

for循环语句

        每循环一次,变量自动加1,使用关键字

for 循环计数器 in 下限..上限loop

  statement1;

  statement2;

end loop;

 

pl/sql

     静态sql

              可以直接在pl/sql中使用的标准sql

     1 dml语句

              2   事物控制语句

      begin

          insert into host(id) values('10.0.0.11');

          commit;

      end;

     动态sql

              1    本地动态sql执行ddl语句:

        begin

           execute immediate'create tabletest(c1 number)';

        end;

 

 

//把表插入1~1000

begin

  execute immediate 'create table ssllff(c1 number)';

end;

begin

    for i in 1 .. 1000 loop

    insert into ssllff values(i);

    end loop;

    commit;

end;

 

匿名块(编译,执行不分)

begin

    for i in 1 .. 1000 loop

    insert into ssllff values(i);

    end loop;

    commit;

end;

sql语句编译在sql/sql匿名块编译时发生

 

--方法二

begin

 execute immediate 'create table testslf(c1 number)';

 for i in 1 .. 1000 loop

      execute immediate 'insert into testslfvalues('||i||')';

 end loop;

end;

 

 

有名块(编译 执行分开)

 procedure

 function

 

select语句的实现

       当且仅当返回一条记录

                用select....into ....语句实现

      declare

        v_id number(10) := 1011;

        v_realname account.real_name%type;

      begin

        select real_name into v_realname fromaccount where id=v_id;

      end;

 

               --列出id为1011的用户名和身份证号

     declare

       v_id number(10) := 1011;

       v_realname account.real_name % type;

       v_idcard_no char(18);

     begin

       select real_name,idcard_no intov_realname,v_idcard_no from account where id = v_id;

       dbms_output.put_line(v_realname);

       dbms_output.put_Line(v_idcard_no);

     end;

 

              若查询结果是单行多列,用复合类型record记录类型

         declare

           type t_rec is record  --定义t_rec的记录类型,

           (realname varchar2(20),

            idcard_no char(18),

            birthdate date);

         v_account t_rec; --v_account是记录类型(t_rec类型)

              记录类型变量的属性引用方法是:变量名.属性名

         v_account.realname := 'huangrong';

           

     %rowtype用表结构或视图结构定义变量

         v_cost cost%rowtype;

 

--提供客户ID,打印用户的姓名和身份证号,若用户不存在,打印该客户不存在

 declare

    v_id number(10) := 1111;

    type v_rec is record

    (realname account.real_name % type,

     idcardno account.idcard_no % type);

     v_account v_rec;

     v_cnt number;

 begin

    select count(id) into v_cnt from account whereid = v_id;

    if v_cnt = 1 then

      select real_name,idcard_no into v_accountfrom account where id = v_id;

     dbms_output.put_line('['||v_account.realname||' ,'||v_account.idcardno||']');

    else dbms_output.put_line('account notexists!');

    end if;

 end;           

 

        返回0条或多条记录: 用cursor实现

      cursor SQL语句

                      隐式cursor:

           insert into update delete DMLselect....into.....

                              属性:目的获取有关隐式cursor的状态信息

                sql%isopen boolean  dml执行中为true,结束为false

                sql%notfound  boolean与sql%found相反

                sql% found  boolean 值为true表示dml操作成功

                sql%rowcount  数值   表示dml语句成功执行的数据行数

        

                      显式cursor:

            declare        

              cursor c_account is select real_name,idcard_nofrom account;

                              属性:目的获取有关显式cursor的状态信息

               %isopen 布尔  如果cursor是open的,其值为true

               %notfound  布尔   如果前一个fetch语句没有返回一行记录,值为true

               % found 布尔   如果前一个fetch语句返回记录,值为true

               %rowcount  数值  到目前为止,cursor已提取的总行数

    

 

declare

 cursor c_account is

    select real_name,idcard_no from account;

 v_acccount c_account % rowtype;

begin

 open c_account;

 loop

    fetch c_account into v_acccount;       

    exit when c_account % notfound;

   dbms_output.put_line(v_acccount.real_name||' '||v_acccount.idcard_no);

 end loop;

 close c_account;

end;

--方法2    while循环

declare

 cursor c_account is

    select real_name,idcard_no from account;

 v_acccount c_account % rowtype;

begin

 open c_account;    

    fetch c_account into v_acccount;

    while c_account%found loop  

     dbms_output.put_line(v_acccount.real_name||' '||v_acccount.idcard_no);

      fetch c_account into v_acccount;

 end loop;

 close c_account;

end;

--没有记录的时候也不会报错

 

--方法3 for循环

declare

cursor c_account is

    select real_name,idcard_no from account;

begin

for i in c_account loop  --i是记录类型

  dbms_output.put_line(i.real_name||' '||i.idcard_no);

  end loop;

end;

  

select into 一条记录

单行单列:into 标量记录

单行多列:into record(type isrecord,tabname%rowtype,curname%rowtype)

0条或多条记录:cursor

 

 

 

pl/sql client-->serverprocess(oracletarena)

server process

(pl/sql engine,sql engine)

 

在pl/sql中如何些下面

DDL:本地动态sql  execute immediate

DML:静态sql(直接表达),本地动态sql

用pl/sql实现先建表再插入数据

因为ddl必须用动态sql,所以dml只能用动态sql

 

表存在,直接插入数据,静态dml

TCL :commit  rollback 放在循环外

select:select into+变量  当且仅当返回一条记录

        sursor 0 条或多条(不报错)fetch into +变量

变量(标量:单行单列)         复合(record:单行多列)

declare

 type 数据类型 record 自定义数据类型

      变量

      标量   预定义数据类型

      复合    自定义数据类型

 cursor

 

collection集合

分类

1 Associative array(关联数组) 又称index-by table用键值访问

2 Nested table 嵌套表

 

 

关联数组:(赋值打印)

declare

type t_indtab is  table of number

index by binary_integer;

v_indtab t_indtab;

begin

v_indtab(1):=1;

v_indtab(2):=2;

v_indtab(10):=10;

v_indtab(5):=5;

dbms_output.put_line(v_indtab(1));

dbms_output.put_line(v_indtab(2));

dbms_output.put_line(v_indtab(10));

dbms_output.put_line(v_indtab(5));

end;

 

关联数组:(赋值,循环打印)

set serveroutput on;

declare

 type t_indtab is table of number

  indexby binary_integer;

 v_indtab t_indtab;

begin

 v_indtab(1):=1;

 v_indtab(2):=2;

 v_indtab(5):=30;

 v_indtab(4):=40;

 for i in v_indtab.first .. v_indtab.last loop

      if v_indtab.exists(i)then

         dbms_output.put_line(v_indtab(i));

      endif;

 end loop;

end;

关联数组的方法:

exists:

count:

first和last

prior和next

trim

delete

 

--赋值,循环打印

declare

 type t_indtab is table of number

 index by binary_integer;

 v_indtab t_indtab;

 v_index binary_integer;

begin

 v_indtab(0):=1;

 v_indtab(2):=2;

 v_indtab(5):=30;

 v_indtab(4):=40;

 v_index := v_indtab.first;

 while v_index <= v_indtab.last

    loop

      dbms_output.put_line(v_indtab(v_index));

      v_index:=v_indtab.next(v_index);

    end loop;

end;

 --v_index:=v_indtab.next(v_index);值的改变情况 0 -->2-->4-->5

 

--account 表中的real_name存入关联数组,下标用帐务帐号id,遍历这个关联数组

declare

 cursor c_account is select id,real_name from account ;

 v_index binary_integer;

 type t_account is  table ofvarchar2(20) index by binary_integer;

 v_account t_account;

 

begin

 for i in c_account loop

    v_account(i.id):=i.real_name;

 end loop;

 v_index := v_account.first;

 while v_index <= v_account.last loop

    dbms_output.put_line(v_index||'   '||v_account(v_index));

    v_index := v_account.next(v_index);

 end loop;

end;

 

--account 表中的real_name,idcard_no存入关联数组,下标用帐务帐号id,遍历这个关联数组

declare

 cursor c_account is select id,real_name,idcard_no from account ;

 v_index binary_integer;

 type namecard is record(

 real_name varchar2(20),

 idcard_no char(18));

 type t_account is  table ofnamecard index by binary_integer;

 v_account t_account;

 

begin

 for i in c_account loop

    v_account(i.id).real_name:=i.real_name;

    v_account(i.id).idcard_no:=i.idcard_no;

 end loop;

 v_index := v_account.first;

 while v_index <= v_account.last loop

    dbms_output.put_line(v_index||'   '||v_account(v_index).real_name

    ||' '||v_account(v_index).idcard_no);

    v_index := v_account.next(v_index);

 end loop;

end;

 

关联数组的初始下标不能为空

关联数组的初始化下标对应的内容不能为空

 

--是关联数据,其中元素的数据类型是record

select real_name,idcard_no bulkcollect  into v_account from account;

 

--打印每个客户的名字,姓名,年龄以及累计年龄

declare

 sumage binary_integer:=0;

 

 type namecard is record(

 real_name varchar2(20),

 age binary_integer);

 

 type t_account is  table ofnamecard index by binary_integer;

 v_account t_account;

begin

 select real_name,round((sysdate-birthdate)/365) age

 bulk collect  into v_account

 from account;

 

 if v_account.count <> 0 then

 for i in v_account.first .. v_account.last

 loop

    sumage:=sumage+v_account(i).age;

   dbms_output.put_line(v_account(i).real_name||'  '||v_account(i).age||'  '||sumage);  

 end loop;

 else

    dbms_output.put_line('no account!');

 end if;

end;

 

 

Exception

pl/sql错误

1 编译时错误

2 运行时错误

     1 oracle错误(ora-xxxxx)

     2 pl/sql运行错误

              3   用户定义的条件

异常的类型

1 隐式触发

    1)oracle预定义异常

                  (例如:no_data_found(出现在select into 或者引用的时候找不到元素),

        too_many_rows(select into行多的异常),

        invalid_cursor(fetch一个关闭的cursor),

        zero_divide(0不能被除),

        dup_val_on_index(唯一性索引异常)

        value_error(错误的值引用))

--预定义异常

declare

 sumage binary_integer:=0;

 

 type namecard is record(

 real_name varchar2(20),

 age binary_integer);

 

 type t_account is  table ofnamecard index by binary_integer;

 v_account t_account;

begin

 select real_name,round((sysdate-birthdate)/365) age

 bulk collect  into v_account

 from account where 1= 2;

 

  for i in v_account.first .. v_account.last

 loop

   sumage:=sumage+v_account(i).age;

   dbms_output.put_line(v_account(i).real_name||'  '||v_account(i).age||'  '||sumage);  

 end loop;

exception

 when value_error then

    dbms_output.put_line('no account');

end;

 

 

          2) 非oracle预定义异常

                      声明:exception_nameexception;

                      与oracle错误号关联:pragma exception_init(exception_name,-2291)

                      捕获异常:whenexception_name then....

 

 

2 显式触发

           用户自定义异常

                   1 > 声明异常

                   2 > 异常发生时用raise触发异常

                   3 > 异常处理部分捕获异常

 

子程序sub program

匿名子程序

          匿名块不存在数据库中

          每次使用时都会进行编译

          不能在其他块中相互调用

有名子程序

         命名的pl/sql,编译并存存在数据库中,可以在任何需要的地方调用

         子程序的组成部分:

                   子程序头

                   声明部分

                    可执行部分

                    异常处理部分(可选)

有名子程序的分类

procedure:过程

function:函数

package:包

trigger:触发器

 

创建存储过程

create or replace proceduresllaccountnum

is

v_cnt binary_integer;

begin

select count(id) into v_cnt fromaccount;

dbms_output.put_line('accountnumber is '||v_cnt);

end;

 

begin

sllaccountnum;  --调用sllaccountnum

end;

--过程没有返回值,直接调用

selectobject_name,object_type,status from user_objects;

 

--存储过程中的参数

create or replace procedurepslfs1

(p_in in varchar2,

 p_out out varchar2,

 p_inout in out varchar2)

 is

 v_in varchar2(10);

begin

 v_in := p_in||'d';

 p_out := p_out||'d';

 p_inout := p_inout||'d';

end;

/*  in (缺省)in的值写入的值不能发生改变

  out   参数不能将值传入,即所有out值都为空

*/

declare

v_in varchar2(10):='abc';

v_out varchar2(10) :='abc';

v_inout varchar2(10) :='abc';

begin

pslfs1('abc',v_out,v_inout);

dbms_output.put_line(v_in);

dbms_output.put_line(v_out);

dbms_output.put_line(v_inout);

end;

 

 

 

提供一个客户编号,返回这个用户的名称年龄

create or replace function sdde(sid number,sage out number)

return varchar2

is

type t_account is record(namevarchar2(20),age binary_integer);

v_account t_account;

 

begin

 select real_name,round((sysdate-birthdate)/365) age into v_account fromaccount where id =sid;

 sage:=v_account.age;

 return v_account.name;

exception

 when no_data_found then

 dbms_output.put_line('not found this account');

 return null;

end;

 

 

declare

age number;

begin

dbms_output.put_line(sdde(1111,age)||age);

end;

 

  

pl/sql块

匿名块

有名块 过程

 

关联数组

select 返回多条记录

cursor while fetch into 变量

变量  集合类型(关联数组 )  元素类型  记录类型

 

declare

关联数组类型定义type t_indtab is table of index by

v_indtab t_indtab

begin

cursor while fetch into 变量

select bulk collect into 变量;

 

遍历关联数组

用关联数组的方法first  last nextcount 

for i in v_indtab.first ..v_indtab.last  简单       下标连续(下标不连续时效率低,空转)          异常处理

while  效率高(有多少个元素,循环多少次)    没有异常处理

 

异常处理

预定义异常

 非oracle预定义异常

 

有名块procedure

数据库对象

create or replace procedure

编译存储过程

uer_objects    编译不成功invalid不可以调用

                                        编译成功valid可以调用

调用(执行)存储过程

begin

     过程名;

end;

exec 过程名

 

参数 in out  inout

--模式为inout或out的形参对应的实际参数必须是变量

过程本身没有返回值

过程能返回值?能 out inout

in 实参-->形参(过程开始执行)

out 实参< --形参(过程执行结束)

inout实参< -->形参(过程开始执行实参-->形参,过程执行结束形-->实参)

 

tarena用户

授予对象权限grant select on account to jsd1303;

sys用户

授予系统权限grant create table to jsd1303;

角色

create role rolename;

grant  to role;

 --通过角色授权

connect:create session,createtable..

--直接授权

grant create table to jsd1303;

 

jsd1303通过角色role获得权限

role:方便权限管理

role:enable(生效)disable(失效)

alter table test drop primarykey;

alter table test add primarykey(c1);

 

alter table test disable primarykey;

alter table test enable primarykey;

 

role:

role enable有权限

role disable没权限

 

匿名块的编译和执行在一起

有名块编译和执行分开,role在编译和执行时的角色状态不一样(enable disable)

oracle解决办法,所有通过角色授予的系统权限不能用,在存储过程中需要的系统权限必须通过直接授予的方式。

 

hiloo用户操作jsd1303用户的表

1 jsd1303授予用户hiloo对表的操作权限(dml select)

grant select on test to hiloo;

grant insert on test to hiloo;

hiloo通过任何client程序对jsd1303的表的操作

 

2 jsd1303 不授予hiloo对表的操作权限,jsd1303创建存储过程(对自己表的操作),jsd1303授予hiloo用户对存储过程的执行权限(jsd1303中存储着对表的操作s1,赋予hiloo用户有s1执行权限)

grant execute on proc1 to hiloo;

 

--绑定变量(:变量名)

create or replace proceduresdsde(

       sid number,sage out number,sname outvarchar2)

is

type t_account is record (

     name varchar2(20),age binary_integer);

v_account t_account;

begin

selectreal_name,round((sysdate-birthdate)/365) age

        into v_account from account where id =sid;

sage:=v_account.age;

sname:=v_account.name;

exception

 when no_data_found then

 dbms_output.put_line('not found this account');

end;

 

variable v_realname varchar2(20)

variable v_age number

execsdsde(1011,:v_age,:v_realname)

print v_realname

print v_age

 

静态sql

编译存储过程时编译sql语句,预编译,sql语句是在pl/sql编译阶段编译的。

例如

create or replace procedure p1

is

begin

for i in 1 .. 1000 loop

insert into tes values(i);

end loop;

commit;

end;

 

/*  for i in 1 .. 1000 loop 

      insert into tes values(i)

    end loop;

可以解析为insert into tes values(:i)using i 

*/

 

动态sql  编译存储过程时不编译sql语句,执行的时候才编译

create or replace procedure p1

is

begin

for i in 1 .. 1000 loop   (statment jdbc)

execute immediate 'insert intotes values('||i||')';

end loop;

commit;

end;

 

动态绑定sql (preparedstatement)

create or replace procedure p1

is

begin

for i in 1 .. 1000 loop

execute immediate 'insert intotes values(:i)'using i;

end loop;

commit;

end;

 

----------------------对比

静态sql: insert into tes values(i);减少软分析此说以及硬分析次数

动态sql: execute immediate 'insert into tes values('||i||')';

动态绑定sql : execute immediate 'insert into tes values(:i)'using i; 减少硬分析次数

静态sql性能 > 动态sql

 

declare

e_notable exception;

pragmaexception_init(e_notable,-942);

begin

execute immediate 'drop tablesssll ';

execute immediate 'create tablesssll(c1 number)';

exception

 when e_notable then

 execute immediate 'create table sssll(c1number)';

end;

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

declare

v_cnt binary_integer;

begin

select count(*) into v_cnt fromuser_tables where table_name = 'SSSLL';

if v_cnt = 0 then

execute immediate 'create tablesssll(c1 number)';

else

execute immediate 'drop tablesssll ';

execute immediate 'create tablesssll(c1 number)';

end if;

end;

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

set serveroutput on

variable j number;

begin

:j:=10;

dbms_output.put_line(:j);需要输入J绑定,结果为绑定的值

end;

print j  --10

 

 

 

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

create sequece s1

start with 1

maxvalue 5

 

select sl1.nextval from dual;

-- sequence SL1.NEXTVAL exceedsMAXVALUE and cannot be instantiated

 

create sequence dsl1

start with 1

maxvalue 5 cycle;

--number to CACHE must be lessthan one cycle

 

create sequence dsl1

start with 1

maxvalue 5 cache 4 cycle;--catche要小于maxvalue并且比start with大

 

select dsl1.nextval from dual;--从1到5循环不断

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

函数function

 

/*select text user_source wherename='FAC1';--获得fun1的源码*/

create or replace function fac1

(p_in number,p_out out number)

return number

is

begin

p_out:=2;

return p_in;

end;

--调用方法的方式1

declare

a number;

b number:=22;

begin

a:=fac1(10,b);

dbms_output.put_line(a);

end;

--调用方法的方式2

declare

v_out number;

v_fac1 number;

begin

v_fac1:=fac1(10,v_out);

dbms_output.put_line(v_fac1);

end;

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

提供客户id,返回用户姓名和年龄,若该客户不存在,返回Null

create or replace function getnameandage2

(p_in number,p_age out number)

return varchar2

is

p_name  varchar2(20);

v_errm varchar2(2000);

begin

selectreal_name,round((sysdate-birthdate)/365) age

into p_name,p_age from accountwhere id = p_in;

return p_name;

exception

when no_data_found then

return 'null';

when others then

v_errm:=sqlerrm;

return v_errm;

end;

 

drop function getnameandage2;

 

declare

vv_age number;

begin

dbms_output.put_line(getnameandage2(1011,vv_age));

dbms_output.put_line(vv_age);

dbms_output.put_line(getnameandage2(1111,vv_age));

end;

 

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

declare

      自定义数据类型(复合数据类型记录record,关联数组is table of  index by)

      变量

 cursor

 exception

 procedure

 function

begin

 

package,package body

1    开发并行,开发效率高

2    程序之间的依赖度底,降低编译程序的次数

 

create or replace package ppp

is

 type t_rec is record(m1 number,m2 varchar2(10));

 v_rec t_rec;

 procedure pr1;

 function fadd(p_in number)return number;

end;

 

 

create or replace package bodyppp

is

 procedure pr1

 is

 begin

  dbms_output.put_line(v_rec.m1);

 end;

 function fadd(p_in number)return number

 is

 begin

  return p_in;

 end;

end;

 

begin

 ppp.v_rec.m1:=ppp.fadd(10);

 ppp.pr1;

end;

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

包的优点

1 方便对存储过程和函数的安全性管理

           整个报的访问权限只需一次性授权

            区分公用 过程和私有过程

2 改善性能

          包被首次调用时作为一个 整体全部调入内存

          减少多次调用时的磁盘I/O次数

包内定义的变量的范围:session级,只要session不关闭就不会改变

如果重新连接session则,值为null;

--alter package ppp compile;重新编译包

 

变量

     局部变量  declare..begin,functionis ..begin,procedure is ... begin

    全局变量(session代码不能重新编译)packageis...end

    绑定变量:sqlplus宿主变量

 

--定义包包含通过用户id调用用户姓名和年龄的函数,以及过程打印函数值的过程

create or replace packageslfgetaccount

is

 type t_rec is record(tname varchar2(20),age binary_integer);

 v_rec t_rec;

 function slfgna(p_id number)return t_rec;

 procedure printrec;

end;

 

create or replace package bodyslfgetaccount

is

  function slfgna(p_id number)return t_rec

  is

  begin

     selectreal_name,round((sysdate-birthdate)/365) age

     into v_rec from account where id = p_id;

     return v_rec;

  exception

     when no_data_found then

     v_rec.tname:='no account';

     v_rec.age:=0;

     return v_rec;  

  end;

  procedure printrec

  is

  begin

     dbms_output.put_line(v_rec.tname||'  '||v_rec.age);

  end;  

end;

 

begin

 slfgetaccount.v_rec:=slfgetaccount.slfgna(1111);

 slfgetaccount.printrec;

end;

--------方法2

create or replace packageslfgaccount

is

 type t_rec is record(tname varchar2(20),age binary_integer);

 function slfgna(p_id number)return t_rec;

 procedure printrec(p_id number);

end;

 

create or replace package bodyslfgaccount

is

  function slfgna(p_id number)return t_rec

  is

  v_rec t_rec;

  begin

     selectreal_name,round((sysdate-birthdate)/365) age

     into v_rec from account where id = p_id;

     return v_rec;

  exception

     when no_data_found then

     v_rec.tname:='no account';

     v_rec.age:=0;

     return v_rec;  

  end;

    procedure printrec(p_id number)

    is

    v_rec t_rec;

    begin

     v_rec:=slfgna(p_id);

     dbms_output.put_line(v_rec.tname||'  '||v_rec.age);

    end;  

end;

 

begin

 slfgaccount.printrec(1111);

end;

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

触发器trigger

create table ssll(c1 numberprimary key,c2 number);

 

create or replace triggerslltrigger

before update

on ssll

for each row

declare

begin

end

/*在给ssll表作update之前作declare begin end操作*/

触发时间:update

before update on test for eachrow  --行级before触发

before update on test   --语句级before触发

after update on test for each row  --行级after触发

after update on test     --语句级after触发

行级 、语句级触发器的区别

before   语句级  在sql语句执行之前执行一次

before 行级   sql语句影响的每条记录被update delete insert之前执行一次

after  行级  sql语句影响的每条记录被update delete insert 之后执行一次

after 语句级  在sql语句执行之后执行一次

 

before语句级

before行级

after行级

before行级

after行级

before行级

after行级

。。。。。

after语句级

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

create table ssll(c1 numberprimary key,c2 number);

 

create sequence ssdd1;

create or replace triggerslltrigger

before insert

on ssll

for each row

declare 

begin

 select ssdd1.nextval into :new.c1 from dual;

end;

 

insert into ssll(c2) values(2);--1,2

select * from ssll;

insert into ssll values (100,10);--2,10

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

 

create table ppsss(c1 numberprimary key);

create table ccss(c1 number,c2number references ppsss(c1));

create or replace triggerup_cascade

after update on ppsss

for each row

declare

begin

 update ccss set c2 = :new.c1 where c2 =:old.c1;

end;

 

insert into ppsss values(1);

insert into ppsss values(2);

insert into ccss values(1,1);

update ppsss set c1 = 10 wherec1=1;

select * from ccss;

 


你可能感兴趣的:(培训日志,oracle)