ORACLE基本语法2021-01-27

1.建表的语法

create table 表名(

字段名(列名) 字段类型 [约束 默认值],

.....

字段名(列名) 字段类型 [约束 默认值]

);

注意:1.表名,字段名,关键字大小写忽略

   2.表名,字段名不能使用关键字

   3.表名,字段名不可以使用数字开头,中间不能出现特殊符号

   4.表名,字段名长度不能超过30个字符

   5.表名,字段名定义需要有含义

2.创建一个用户表 t_user

|-姓名name,字符串

|-性别gender,字符串

|-年龄age,数字型



create table t_user(

 name varchar2(30),

 gender varchar2(3),

 age number

);  

--注意: desc命令必須在命令窗口中執行.在sql window中不能執行

desc t_user;   

3.Oracle中常见的数据类型

字符串

 |-varchar2(length):可变长的字符串,length定义最长字符串的字节数.

                    length最大值位4000,节省空间,查询效率低

 |-char(length):定长的字符串,length定义最长的字符串的字节数,最大值2000

                浪费空间,查询效率高

 |-varchar(length):等价于varchar2(length),varchar2是Oracle独有的. 

数字类型

 |-number(p,s):p表示定义数字的长度(不包含小数点),s表示小数点后面的尾数

    |-定义商品的价格 number(5,2),表示小数点前面有3个数字,后面有两个数字

         123.23  12.23(合法,在精度里面)  1234.10(不合法) 

    |-number:表示描述整数  

日期类型

 |-date:七个字节,如果是英文环境 DD-MOR-RR "11-JUN-15" 如果是中文环境 15-7月-15

4.删除表 drop table 表名

drop table test2;





create table  test2(

 str varchar(200)

);

5.创建表员工表 t_emp

|-员工id 长度最长为11的整数

|-员工姓名 name

|-员工工资 salary 12345.12

|-生日 birth 日期

|-职位 job 字符串

|-员工性别 gender

 create table t_emp(

   id number(11),

   name varchar2(30),

   salary number(7,2),

   birth date,

   job varchar2(30),

   gender char(3)

 );

--使用default设置字段的默认值

drop table t_emp;--将性别默认值为M

create table t_emp(

  gender char(3) default 'm'  /*单引号表示字符串*/

 

);

--使用not null设置字段值不能为空

create table t_emp(

 name varchar2(30) not null

);

6.使用ALTER修改表结构

 --添加新的字段

   语法:alter table  表名 add (新的字段 字段类型,...); 

   --想t_emp表中追加deptno的字段

   alter table t_emp add(deptno number(11));

 --删除字段

   语法:alter table 表名 drop column 字段名;

   --删除t_emp表中的gender字段

    alter table t_emp drop column gender;

 --修改列名

    语法:alter table 表名 rename column 旧列名 to 新列名;   

   --将t_emp表中的deptno修改为dept_no

   alter table t_emp rename column deptno to dept_no;

 --修改字段类型

    语法:alter table 表名 modify (列名 新类型,...);

    --将t_emp表的salary的类型修改为number(5,2)

    alter table t_emp modify (salary number(5,2));

7.truncate:删除表中的数据

语法:truncate table 表名;



truncate只是清空表中的数据,但是保留表的结构

drop:将表结构删除

8.DML语句:操作表数据

|-8.1 插入数据 insert into

      |-语法 INSERT INTO 表名 [(字段名,...)] VALUES(值,...)

      --注意:如果是向表中的所有字段添加数据时,可以省略字段名

--向t_emp表中插入数据

--开发中推荐使用明确字段名

insert into t_emp(id,name,salary,birth,job,dept_no)

           values(1001,'yves',123.23,sysdate,'开发',10);

--不便于维护

insert into t_emp values(1003,'yvesHe',123.45,sysdate,'测试',20);

commit;--提交数据

查询表中的所有数据:select * from 表名;-- *通配符,表示所有的字段

|-8.2 删除数据 delete

     |-语法:delete from 表名 [where 过滤条件];  

     delete from t_emp;   --注意:将表中的数据全部删除 

     /*删除数据通常使用where条件

     */

     //删除id=1001的用户

     delete from t_emp where id=1001;/*where是过滤条件*/

delete和truncate的区别?

 |-1.delete属于DML语句,需要事务的支持

 |-2.truncate属于DDL语句,无需事务的支持      

 |-3.delete需要回滚内存空间,truncate无需回滚内存空间

 |-4.delete性能要低于truncate 

 |-5.delete保留高水位线,truncate删除高水位线 

/*

DML语句需要事务的管理:

   commit提交数据

   rollback回滚数据

  

  

*/ 

|-8.3 修改记录 update

      |-语法:update 表名 set 字段名=值[,....] [where 过滤条件];

     

      update t_emp set name='jerry';

      //将id=1001的用户名改为 jerry,工资改为 888

      update t_emp set name='jerry',salary=888 where id=1001;

9.事务控制语句(配合DML语句一起使用)

commit:提交事务

rollback:事务回滚   

savepoint 事务保存点  



create table temp( id number);  



insert into temp values(1);

insert into temp values(2);

savepoint A;--设置事务的保存点

insert into temp values(3);

insert into temp values(4);

insert into temp values(5);

savepoint B;

insert into temp values(6);

insert into temp values(7);

savepoint C;

insert into temp values(8);

rollback to B;--回滚到保存点B,数据到5

rollback to A;--可以成功,数据到2

/*rollback to C 报错,事务已经到了B,C不存在了*/



select * from temp;

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

1.补充的函数

coalesce(参数列表):返回参数列表中第一个非空参数,最后一个参数通常为常量

--案例:

年终提成:

 |-1.如果员工的comm不为空,发comm

 |-2.如果员工的comm为空,发工资的一半

 |-3.如果sal和comm为空,发100安慰

select ename,sal,comm,coalesce(comm,sal*0.5,100) comms

from emp;

case语句:类似于java中的switch语句

case 表达式

 when 值 then 执行的语句 /*没有逗号*/

   ...

 when 值 then 执行的语句

 else 执行语句  /*类似于switch语句中的default*/

end;

--加薪

|-ANALYST职位,提高10%

|-SALESMAN,提高5%

|-CLERK,提供2%

select ename,sal,job,

 case job

   when 'ANALYST' then sal*1.1

   when 'SALESMAN' then sal*1.05

   when 'CLERK' then sal*1.02

   else sal

 end new_sal

from emp;

decode(判断条件,匹配1,值1,匹配2,值2,...,默认值):函数,是case语句的简写

--加薪

|-ANALYST职位,提高10%

|-SALESMAN,提高5%

|-CLERK,提供2%



select ename,sal,job,

decode(job,'ANALYST',sal*1.1,'SALESMAN',sal*1.05,'CLERK',sal*1.02,sal) new_sal

from emp;

2.单行函数:一条数据经过函数处理获得一条结果.

组函数:多条记录经过组函数的处理只会得到一条结果

常见的组函数

|-count(表达式):计数

  --统计员工表中有多少个员工

  select count(*) from emp;

  select count(ename) from emp;

  --员工表中有多少个员工有提成

  select count(comm) from emp;--可以进行空值处理

  --员工表中有多少个职位

  select count(distinct job) from emp;

|-max():最大值,min()最小值,avg()平均值,sum()求和

--员工表中最高的工资

select max(sal),min(sal),sum(sal),count(ename),avg(sal) from emp;

--求平均值是需要注意空值处理 

select sum(comm),avg(nvl(comm,0)),count(ename) from emp;

--获得每个职位的平均工资,最大值,最小值

group by:分组的关键子

select job,max(sal),min(sal),avg(sal)

from emp

group by job;--表示根据职位进行分组

--获得每个部门的平均工资,最大值,最小值

select deptno ,max(sal),min(sal),round(avg(sal)) avg_sal

from emp

group by deptno

order by avg_sal;

注意:如果select后面出现了组函数,那么其他内容必须出现在 group by 子句中.

--获得平均工资大于2000的职位

select job,round(avg(sal)) avg_sal

from emp

group by job

having round(avg(sal))>2000;/having是对分组后的结果进行过滤,不能使用别名/

having和where的区别

  |-where是对表中的数据进行过滤,先执行

  |-having是对分组后的结果进行过滤,如果有where先执行where然后分组

--获得管理者下面的员工的平均工资, 最低工资不能少于800,没有管理者的不参与统计

select mgr,round(avg(sal)),min(sal)

from emp

where mgr is not null /1.where先执行/

group by mgr /2.分组/

having min(sal)>800; /3.对分组的结果进行过滤/

--获得各个部门中工资大于1500的员工人数(先过滤再分组)

    select deptno,count(*)

    from emp

    where sal>1500  /*先过滤*/

    group by deptno;

--平均工资最高的部门

 select  max(avg(sal))

 from emp

 group by deptno;

--那些职位的人数超过2个人,对人数进行排序

select job,count(ename) nums

from emp

group by job

having count(ename)>2

order by nums ; /注意order by需要保存到最后面/

--薪水最高的员工

select max(sal) from emp;--获得最高薪水

select * from emp where sal=5000;

子查询:在主查询执行之前执行,将执行的结果作为主查询的一个判断依据

select ename,sal,deptno

from emp

where sal=(select max(sal) from emp);

注意:1.子查询需要定义在括号当中

    2.子查询通常定义在条件判断的右边

    3.在子查询中不建议使用 order by

--查询谁的薪水比 BLAKE 高

 select ename,sal

 from emp

 where sal>(select sal from emp where ename='BLAKE') ;/*避免值过多*/

 /*如果子查询的结果为null 那么结果为null*/

 select ename,sal

 from emp

 where sal>(select sal from emp where ename='yves') ;

--子查询中多行比较符

 in :等于列表中的任何一个

 any:和子查询结果中的任意一个值进行比较

 all:和子查询结果中的所有值进行比较

--获得各个部门中工资最高的员工

select ename,sal,deptno

from emp

where (deptno,sal) in (select deptno,max(sal) from emp group by deptno);

--谁的工资比20号部门员工的工资都高

select ename,sal,deptno

from emp

where sal>all(select sal from emp where deptno=20) ;/all大于最大值/

select ename,sal,deptno

from emp

where sal>any(select sal from emp where deptno=20) ;/any 大于最小值/

--获得SIMTH 的同部门的员工,除了SIMTN以外

select ename,deptno

from emp

where deptno in (select deptno from emp where ename='SMITH') /in 可能其他部门有同名的人/

and ename!='SMITH';/ename <> 'SMITH'/

关联子查询:子查询不再是一个独立的SQL语句,依赖外部的主查询传入的参数.

--那些员工的薪水比公司的平均薪水低(非关联子查询实现)

select ename,sal

from emp

where sal<(select avg(sal) from emp);

--那些员工的薪水比本部分的平均薪水要低

select ename,sal,deptno

from emp e /为当前的emp表取别名/

where sal<(select avg(sal) from emp where deptno=e.deptno);

--有下属的员工

select empno,ename,deptno

from emp e

where exists (select 1 from emp where mgr=e.empno);

注意: exists:如果子查询的有结果返回,true,如果没有结果返回为false,所以exists不关心

子查询的结果,通常返回一个常量 1,获得定义一个任何字段

select * from emp;

select distinct mgr from emp where mgr is not null;

哪些人不是下属

select empno,ename,deptno

from emp e

where not exists (select 1 from emp where mgr=e.empno);

select empno,ename

from emp

where empno not in (select distinct mgr from emp where mgr is not null);

注意:not in 当中如果有null那么结果为null

集合的操作

union 去掉重复记录

create table ta( str number);

insert into ta values(4);

insert into ta values(3);

insert into ta values(1);

insert into ta values(2);

create table tb(stb number);

insert into tb values(5);

insert into tb values(3);

ta={4,3,1,2};

tb={5,3};

select * from ta

union /合集/

select * from tb;

ta union tb={1,2,3,4,5};

select * from ta

union all

select * from tb;

ta union all tb={4,3,1,2,5,3};

union和union all的区别

 |-union:去重复,排序

 |-union all:不重复也不排序.(推荐)

select * from ta

intersect /交集/

select * from tb;

ta intersect tb={3};

select * from ta

minus /差集/

select * from tb;

ta minus tb ={1,2,4};

tb minus ta ={5};

连接查询:查询多个视图或者数据表时成为连接查询

  |-内连接:返回所有符合连接条件的记录

  |-外连接:返回符合连接条件的记录,同时返回不符合连接条件的记录(左外连接,右外连接)

  |-全外连接:左外连接和右外连接的结果总和

  |-自连接:数据的来源是一个表表,关联条件来自同一个数据表或者视图中

--查询员工的姓名和所在部门的名称和地区

--采用内连接: 表1 [inner] join 表2 on 关联的条件

select e.ename,d.dname,d.loc,d.deptno

from emp e join dept d on e.deptno=d.deptno;

--inner通常被省略,建议在写关联查询时提供表的别名

select e.ename,d.dname,d.loc,d.deptno

from emp e inner join dept d on e.deptno=d.deptno;

select e.ename,d.dname,d.loc

from emp e,dept d

where e.deptno=d.deptno;

--使用外外连接:

 |-左外连接: 表1  left outer join 表2 on 关联条件

     |-结果集的组成:匹配的数据+表1中没有匹配上的数据(结果集中保留表1的完整性)

 |-右外连接: 表1 right outer join 表2 on 关联条件

     |-结果集的组成:内连接的结果集+表2中没有匹配上的数据(保留表2的完整性)  

 |-左左左全,右右右全    

--获得没有员工的部门

select e.ename,d.dname,d.loc,d.deptno

from dept d left outer join emp e on e.deptno=d.deptno

where e.ename is null;

select e.ename,d.dname,d.loc,d.deptno

from dept d ,emp e

where e.deptno(+)=d.deptno;/保留 d 表的完整性 早期的外连接/

查询并显示SALES部门的职位

select distinct e.job

from emp e join dept d

on e.deptno=d.deptno

where d.dname='SALES';

查询部门的名称,所在地,员工数量,平均工资

select d.dname,d.loc,e.avg_sal,e.count_e

from dept d

join

( select deptno,avg(sal) avg_sal,count(ename) count_e

 from emp

 group by deptno

) e

on d.deptno=e.deptno;

--自连接

查询员工以及上司的名称

select e1.ename employee,e2.ename lidao

from emp e1,emp e2

where e1.mgr=e2.empno;

--全外连接 表1 full outer join 表2

  |-结果集:内连接结果集+左外连接+右外连接

select e.id,e.name,d.name

from temp_emp e full outer join temp_dept d

on e.d_id=d.id;

create table temp_emp(id number ,name varchar2(30),d_id number);

insert into temp_emp values (1001,'yves',1);

insert into temp_emp values(1002,'yvesHe',2);

insert into temp_emp values(1003,'lucy',3);

insert into temp_emp values(1004,'outMan',null);

create table temp_dept(id number,name varchar2(30));

insert into temp_dept values(1,'开发');

insert into temp_dept values (2,'财务');

insert into temp_dept values (3,'测试');

insert into temp_dept values (4,'前台');

3.表的复制:如果需要对表中的数据进行删除和修改,建议通过复制表中的数据来对数据进行操作

create table 表名 as 查询语句;

--将emp表中的数据复制到t_emp表中

create table t_emp

as

select * from emp;

--只需要表的结构

--将emp表的结构复制到t_emp表中

create table t_emp

as

select * from emp

where 1=0;/提供一个否定条件/

--只复制一部分数据

--将emp表中部门10的员工的数据复制到t_emp表中

create table t_emp

as

select * from emp

where deptno=10;

--将emp表中的员工姓名,工资,年薪保存到t_emp表中

create table t_emp

as

select ename,sal,sal12 year_sal /如果字段中出现函数或者计算需要提供别名*/

from emp;

--统计emp表中部门的人数,将部门编码和人数保存到t_emp表中

create table t_emp(did,ecount)

as

select deptno,count(ename)

from emp

group by deptno;

注意:表的复制只会复制表中的数据,不会复制表中的约束

4.伪列

select rowid ,e.* from emp e;

rowid:是一个伪列,Oracle独有的.每一条记录的rowid的记录是唯一的

--删除表中的重复记录

select e.,d.

from emp e,dept d

where e.deptno=e.deptno;/连接条件不合理:产生笛卡尔积/

笛卡尔积产生的原因

 |-1.没有连接条件

 |-2.连接条件无效

避免笛卡尔积的方法:提供合理的连接条件

迪卡集的作用:临时获得大量的测试数据.

create table t_emp

as

select e.*

from emp e,dept d

where e.deptno=e.deptno;

select rowid,e.* from t_emp e;

--删除重复的记录

delete from t_emp where rowid not in(

          select max(rowid) from t_emp group by empno,ename,job,mgr );

select * from t_emp;

rownum:伪列,表示行号

select rownum ,e.* from t_emp e;

--显示t_emp表中前五条记录

select rownum ,e.* from t_emp e where rownum<=5; /rownum最小值从1开始/

--显示t_emp表中第3条到第9条记录

select rownum ,e.* from t_emp e

where rownum>=3 and rownum<=9; /查不出任何结果/

--在Oracle中,使用rownum进行分页查询

select ee.*

from

    (select rownum r,e.* from t_emp e ) ee

where ee.r>=3 and ee.r<=9;

--将t_emp表中按照工资进行排序,显示出第 5条到第10条

select ee.*

from

    (select rownum r,e.* from (select * from t_emp order by sal) e ) ee

where ee.r>=5 and ee.r<=10;

5.约束条件

|-主键约束(PK):primary key

  |-一张表中只能有一个主键约束

  |-主键约束的特点:不能为空,具有唯一性

  |-关系型数据库中使用主键约束唯一标识一行数据

  |-主键约束分为两类

    |-行级约束

    |-表级约束

--建表时定义主键约束

create table 表名(

 字段名 类型 primary key , --列级约束,只能作用一个字段

 ...

);

--建表时定义表级约束

create table 表名(

 字段1 类型,

 字段2 类型,

 ...,

 constraint 表名_字段名_PK primary key(字段1,字段2)  /*字段 1和字段 2 联合作为主键 */

);

非空约束(NN):not null

--语法

create table 表名(

字段名 类型 not null

....

);

--定义非空约束名称

create table 表名(

字段名 类型 constraint 表名_字段名_NN not null,

...

);

注意:非空约束只有列级约束,没有表级约束

唯一性约束(uk):unique:值必须唯一,可以为null

--列级约束

create table 表名(

字段名 类型 unique,

....

);

--表级约束

create table 表名(

字段1 类型,

字段2 类型,

...,

constraint 表名_字段名_uk unique(字段1,字段2)

);

检测约束(CK):check

--列级约束

create table 表名(

字段名 类型 check(字段名 in(值1,...)),

....

);

--表级约束

create table 表名(

字段1 类型,

字段2 类型,

...,

constraint 表名_字段名_ck check(字段1 in(值1,...))

);

--提供一个用户表 t_user

create table t_user(

id number constraint USER_ID_PK primary key,/*表示用户编号,主键*/

name varchar2(30) constraint USER_NAME_NN not null,

gender char(3) default 'F',

constraint USER_NAME_UK unique(name),

constraint USER_GENDER_CK check(gender in('F','M'))

);



user_constraints:数据库提供的查看表中约束条件的



--查询t_user表中的约束条件

select CONSTRAINT_TYPE,CONSTRAINT_NAME from user_constraints where table_name ='T_USER';



insert into t_user values(1001,'yves','F');

insert into t_user values(1001,'yvesHe','M');--报错,违法主键约束





预习:外键约束

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

1.关于tab3表内容:

2005-05-09 胜

2005-05-09 胜

2005-05-09 负

2005-05-09 负

2005-05-10 胜

2005-05-10 负

2005-05-10 负

如果要生成下列结果, 该如何写sql语句?

/建表/

create table tab3(

playday date,

result varchar2(3)

);

insert into tab3 values(to_date('2005-05-09','yyyy-MM-dd'),'胜');

insert into tab3 values(to_date('2005-05-09','yyyy-MM-dd'),'胜');

insert into tab3 values(to_date('2005-05-09','yyyy-MM-dd'),'负');

insert into tab3 values(to_date('2005-05-09','yyyy-MM-dd'),'负');

insert into tab3 values(to_date('2005-05-10','yyyy-MM-dd'),'胜');

insert into tab3 values(to_date('2005-05-10','yyyy-MM-dd'),'负');

insert into tab3 values(to_date('2005-05-10','yyyy-MM-dd'),'负');

要求:

        胜 负

2005-05-09 2 2

2005-05-10 1 2

方法1:

select playday,

   sum(

   case

     when result='胜' then 1

     else 0

   end

   ) 胜,

    sum(

   case

     when result='负' then 1

     else 0

   end

   ) 负

   from tab3

   group by playday;

方法2:

select playday,

   sum(

    decode(result,'胜',1,'负',0)

   ) 胜,

    sum(

    decode(result,'负',1,'胜',0)

   ) 负

   from tab3

   group by playday;

2.表中有A B C三列,用SQL语句实现:

 当A列大于B列时选择A列否则选择B列,

 当B列大于C列时选择B列否则选择C列。

 /*建表*/

 建立一个表:tab4里面有三个字段:A,B,C

方法1:

select

case

 when A>B then A

 else B

end resultAB,

case

 when B>C then B

 else C

end resultBC

from tab4;

sign比较大小的函数

select sign(-22),sign(100),sign(0) from dual;

/结果为:-1,1,0/

方法2:

select decode(sign(A-B),1,A,B) resultAB,decode(sign(B-C),1,B,C) from tab4;

3.一个日期判断的sql语句

请取出tab5表中日期(SendTime字段)为当天的所有记录?

(SendTime字段为datetime型,包含日期与时间)

/建表:tab5/

select * from tab5 t

where to_char(t.datetime,'yyyy-MM-dd')=to_char(sysdate,'yyyy-MM-dd');

4.有一张表,里面有3个字段:语文,数学,英语。其中有3条记录分别表示

语文70分,数学80分,英语58分,

请用一条sql语句查询出这三条记录并按以下条件显示出来(并写出您的思路):

大于或等于80表示优秀,大于或等于60表示及格,小于60分表示不及格。

   显示格式: 

   语文              数学                英语 

   及格              优秀                不及格   

/建表:tab6/

create table tab6(

语文 number,

数学 number,

英语 number

);

insert into tab6 values(70,80,58);

方法1:case语句

select

(case when 语文>=80 then '优秀'

     when 语文>=60 then '及格'

     else '不及格' end) 语文,

(case when 数学>=80 then '优秀'

     when 数学>=60 then '及格'

     else '不及格' end) 数学,

(case when 英语>=80 then '优秀'

     when 英语>=60 then '及格'

     else '不及格' end) 英语               

from tab6;

方法2:decode

select

decode(sign(语文-80),1,'优秀',0,'优秀',-1,

        decode(sign(语文-60),1,'及格',0,'及格',-1,'不及格')) 语文,

decode(sign(数学-80),1,'优秀',0,'优秀',-1,

        decode(sign(数学-60),1,'及格',0,'及格',-1,'不及格')) 数学,

decode(sign(英语-80),1,'优秀',0,'优秀',-1,

        decode(sign(英语-60),1,'及格',0,'及格',-1,'不及格')) 英语                   

from tab6;

5用一条SQL语句 查询出每门课都大于80分的学生姓名

name kecheng fenshu

张三 语文 81

张三 数学 75

李四 语文 76

李四 数学 90

王五 语文 81

王五 数学 100

王五 英语 90

/建表:/

create table tab7(

name varchar2(30),

course varchar2(39),

score number

);

insert into tab7(name,course,score) values('张三','语文',81);

insert into tab7(name,course,score) values('张三','数学',75);

insert into tab7(name,course,score) values('李四','语文',76);

insert into tab7(name,course,score) values('李四','数学',90);

insert into tab7(name,course,score) values('王五','语文',81);

insert into tab7(name,course,score) values('王五','数学',100);

insert into tab7(name,course,score) values('王五','英语',90);

select distinct name from tab7 where name not in(

select distinct name from tab7 where score<80);

1.标间约束

|-主键约束(PK):primary key

  |-作用:唯一标识一行数据

  |-特点:不能为空,唯一

|-唯一性约束(UK):unique

  |-作用:字段值不能重复

  |-特点:可以为空

|-非空约束(NN):not null

  |-作用:字段值不能为空

  |-注意:非空约束不能定义表级约束

|-检测约束(CK):check

  |-作用:字段值只能在指定的内容中选择  

2.外键(foreign key):在数据库内部,使用外键来描述表与表之间的关系

   有外键列的表称为从表(子表),提供参考值的表称为主表(父表)

   外键字段可以参考主表的主键约束或者唯一性约束的字段

  

  

用户表和订单表

   |-一个用户肯能有多个订单,为了在数据库中描述关系,在订单表中提供外键

  

--用户表

create table t_user(

 id number primary key,

 name varchar2(30) not null

 );

--订单表

create table t_order(

 oid number primary key,/*订单编号*/

 account number(7,2) not null,/*总金额*/

 pronums number not null,/*货品总数*/

 orderday date,/*下单日期*/

 u_id number references t_user(id) /*定义表级的外键约束,参考用户表的中id值*/

);

/注意/

  |-1.建表时:先建主表,在建立从表

  |-2.插入数据时,先操作主表,再操作从表

  |-3.删除数据时,如没有级联操作,必须先删除子表中的数据,在删除主表中的数据

  |-4.删除表结构,要先删除子表

 

/*插入数据*/

insert into t_user values(1001,'yves');

insert into t_user values(1002,'yvesHe');



insert into t_order

    values(231001,250.25,4,to_date('2015-05-29','yyyy-MM-dd'),1001);

insert into t_order

     values(231002,1250.25,4,to_date('2015-05-30','yyyy-MM-dd'),1001);

--插入下列数据出

--ORA-02291: 违反完整约束条件 (SCOTT.SYS_C004141) - 未找到父项关键字

--原因:子表中的外键列必须参考父表中的主键值,必须存在的值

insert into t_order

     values(231002,1250.25,4,to_date('2015-05-30','yyyy-MM-dd'),1003); 

 

 

 

--删除数据

  --执行下条SQL语句出现

  --ORA-02292: 违反完整约束条件 (SCOTT.SYS_C004141) - 已找到子记录

  --原因:主表的当前数据被从表参考.要先删除从表中的数据

  delete from t_user where id=1001;

 

 

  delete from t_order where  u_id=1001;

 

--删除表结构

 --执行下条SQL语句出现

 --ORA-02449: 表中的唯一/主键被外键引用

 --原因:当前表的主键被作为其他表的外键

   drop table t_user;

  

   

--表级约束定义外键  

 --用户表

create table t_user(

 id number primary key,

 name varchar2(30) not null

 );

--订单表

create table t_order(

 oid number primary key,/*订单编号*/

 account number(7,2) not null,/*总金额*/

 pronums number not null,/*货品总数*/

 orderday date,/*下单日期*/

 u_id number, /*定义表级的外键约束,参考用户表的中id值*/

 constraint order_user_id_fk foreign key(u_id) references t_user(id)

);

级联删除:

1.默认情况下,必须先删除从表的数据在删除主表的数据

--如何删除表中的约束

alter table t_order drop constraint order_user_id_fk;

on delete set null:当主表的数据被删除时,子表参考的值设为null

--重新为表t_order添加外键约束

alter table t_order add constraint order_user_id_fk

                   foreign key(u_id) references t_user(id) on delete set null;

 先删除父表

 delete from t_user where id=1001;

 子表t_order中对应的u_id字段的值被置空

on delete cascade :当主表的数据被删除时,子表中对应的值也被删除

--重新为表t_order添加外键约束

alter table t_order add constraint order_user_id_fk

                   foreign key(u_id) references t_user(id) on delete cascade;

 先删除父表

 delete from t_user where id=1001;

 子表t_order中对应的u_id的整条记录被删除

drop table t_order;

drop table t_user;

--用户表

create table t_user(

 id number primary key,

 name varchar2(30) unique  /*唯一性约束*/

 );

--订单表

create table t_order(

 oid number primary key,/*订单编号*/

 account number(7,2) not null,/*总金额*/

 pronums number not null,/*货品总数*/

 orderday date,/*下单日期*/

 u_name varchar2(30), /*定义表级的外键约束,参考的主表的唯一性约束的字段*/

 constraint order_user_id_fk foreign key(u_name) references t_user(name)

);

用户表和身份证

用户表 t_person

身份证 t_idcard

一个用户只能有一张身份证,一张身份证对应一个用户

1对1的描述的策略:唯一外键

create table t_person(

 id number primary key,

 name varchar2(30)

);

create table t_idcard(

 id number primary key,

 serial number, /*有效期 */

 p_id number ,

 constraint idcard_person_id_fk foreign key(p_id) references t_person(id),/*外键*/

 constraint idcard_p_id_uk unique(p_id)/*唯一性约束*/

);

drop table t_idcard;

drop table t_person;

1对1的描述的策略:共享主键

create table t_person(

 id number primary key,

 name varchar2(30)

);

create table t_idcard(

 id number primary key references t_person(id),/*id即为外键又为主键*/

 serial number /*有效期 */

);        

多对多的关系:必须通过第三张表进行描述

--学生表

  create table t_stu(

   id number primary key,

   name varchar2(30)

  );

--课程表

 create table  t_course(

  id number primary key,

  name varchar2(30),

  score number /*总的学分*/

 );  

 

学生表和课程表示多对多,提供第三张关系表

 create table t_s_c(

  id number primary key,

  s_id number references t_stu(id),

  c_id number references t_course(id),

  score number /*某个学生实际的成绩*/

 );  

约束的建立时机:为了更好的对约束条件进行管理,建议对约束进行命名.在建表之后在提供约束

 --添加约束

 alter table 表名 add constraint 自定义约束名 约束条件;

 注意:非空约束,不能定义表级约束

 alter table 表名 modify (字段名 字段列席 not null );



 --删除约束

 alter table 表名 drop constraint 指定的约束名;

3.数据库设计的三范式

|-在数据设计时需要遵守的规则,关系型数据库中对这类规则称为范式.

第一范式:每个字段要确保原子性.每个字段不能再进行分解

第二范式:在第一范式的基础上,确保表中的每一列和主键相关.

第三范式:在第二范式的基础上,却表表中的字段和主键是直接相关而不是间接相关

4.作业

购物系统中的关系

用户表  t_user

商品表  t_product

订单表  t_order

地址表  t_address

订单详细表 t_orderitem

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

1.数据库脚步文件的定义

1.删除约束条件

2.删除表结构(先删除主表再删除父表)

3.建表

4.定义约束条件

5.插入测试数据

2.数据字典

2.1 数据字典的格式

   user_xxx:当前用户自己的对象

   all_xxx:当前用户能够访问的对象(自己的对象+其他用户授权访问的对象)

   dba_xxx:当前数据库所有的对象

  

   user_tables:当前用户中可以操作的表,查询当前用户下的所有的表名

                select table_name from user_tables;

   user_constraints:当前用户所有的约束条件

   user_objects:当前用户包含的对象  

3.数据库的对象

3.1 table 表 :是关系型数据库中基本的存储单元,是一个二维结构由行和列组成.

3.2 view 视图:是一个虚表,视图会对应一个查询语句.将查询语句的结果赋予一个名字,

             就是试图的名称,可以像操作表一样操作视图.视图的目的可以保证表的

             安全和简化查询操作.

3.3 index 索引:在数据库中用来加速查询的数据库对象.减少磁盘的IO操作,提高访问性能

3.4 sequence 序列:用来唯一生成数值的数据库对象.通常使用序列来控制主键值.由数据库内

                 部提供具有安全性和高效性

3.5 procedure 存储过程:在数据库中完成特定的任何和操作.实现小部分的业务逻辑

3.6 function 函数:用来进行复杂的计算,返回结果.

3.7 package 包:将函数和存储过程组织起来,形成程序组.由包头和包体组成

3.8 trigger 触发器:在事件发生时隐式的执行,类似于java中的事件监听器

4.序列 sequence:连续产生不同的数值作为表的主键值

             |-oracle,db2中有序列,mysql,sqlserver没有序列

             |-序列是数据库中独立的对象

--创建序列 :默认从1开始,步进为 1

create sequence mytest_seq;

序列的属性

  |-nextval:获得序列进行步进操作的值,会引起序列值得变化

  |-currval:获得当前序列最大的值,不会引起序列值得变化

访问序列属性:自定义的序列名.nextval / 自定义的序列名.currval

--创建指定的起始值和步进

create sequence 自定义名称 start with 指定的值 increment by 步进;



create sequence test_seq start with 10000 increment by 2;



create table t_test(

  id number primary key ,

  name varchar2(30)

);

insert into t_test(id,name) values(test_seq.nextval,'yves');

insert into t_test(id,name) values(test_seq.nextval,'yves');

insert into t_test(id,name) values(test_seq.nextval,'yves');

insert into t_test(id,name) values(test_seq.nextval,'yves');

insert into t_test(id,name) values(test_seq.nextval,'yves');

insert into t_test(id,name) values(test_seq.nextval,'yves');

--删除序列

drop sequence 序列名;

drop sequence test_seq;--表中的数据不会受影响

5.视图 view

视图的特点

  |-1.简化复制查询的操作

  |-2.隐藏表中字段 

  |-3.视图是虚表,基表数据的影射

简单视图:视图中的数据就是基表中的子集.

drop table t_emp;

--复制emp表

create table t_emp

as

select * from emp where deptno in (10,20);

--使用t_emp表作为基表创建视图

create view v_emp

as

select ename,empno,deptno from t_emp where deptno=20;

--查询视图

select * from v_emp;

--查询视图的结构

desc v_emp;

--更新基表中的数据,那么视图中对应的记录也会变化

update t_emp set ename='yves' where empno=7369;

--更新视图中的数据:简单视图在默认情况下可以通过修改视图影响基表中的数据

update v_emp set ename='yves' where empno=7369;

简单视图防止修改视图影响基表在创建视图时使用 with read only

--删除视图

drop view v_emp;

--创建只读的简单视图

create view v_emp

as

select ename,empno,deptno from t_emp where deptno=20 with read only;

复杂视图:数据是通过基表中的数据计算获得.特点只读.

 |-关联视图:视图中的数据通过多张表联合查询获得

--创建一个试图,显示每个部门有多少员工

create view v_emp_count

as

select deptno,count(ename) emp_num from t_emp group by deptno;

--向基表中插入数据:视图中的数据会变化

insert into t_emp(ename,empno,deptno) values('yves',1001,10);

--修改视图

delete from v_emp_count where deptno=10;

--创建视图可以使用create or replace 进行创建:如果没有创建,有就覆盖

create or replace view v_emp_count

as

select max(sal) max_sal,avg(nvl(sal,0)) avg_sal from t_emp;

--通过数据字典查寻视图

select text from user_views where view_name='V_EMP_COUNT';--视图对应的sql语句

--为scott授予创建视图的权限

使用sys以管理员身份登录

grant create view to scott;

6.索引 index:目的提高查询效率

      |-结构:内容+地址

      |-注意:如果字段有频繁的DML操作那么不适合创建索引(可能造成频繁的创建索引)

建表时对于主键约束和唯一性约束自动创建索引(user_indexes)

 create table t_test(

 id number constraint t_test_id_pk primary key,

 name varchar2(20) constraint t_test_name_uk unique,

 age number constraint t_test_age_nn not null,

 gender varchar2(3) constraint t_test_gender_ck check(gender in('F','M'))

 );



 select index_name,index_type from user_indexes where table_name='T_TEST';   

     

 --对于主键字段和唯一性字段如果有where条件会使用到索引

 select * from t_test where id=1000;

 --如果对索引字段进行的计算,那么不会使用索引

 select * from t_test where id/100=10;   --不会使用索引 

 优化=> select * from t_test where id=1000; --可以使用索引

 --条件查询中没有使用索引字段

 select * from t_test where age=10;--全表扫描



 手动创建索引

 create index 自定义索引名称 on 表名(字段名);



 create index t_test_age on t_test(age);



 删除索引

 drop index 自定义名称;

6.如何进行SQL语句的优化

|-** 在select语句中避免使用 *

|-** 减少数据库的访问次数

|-** 删除重复记录

|-尽量多使用commit

|-** 使用where替换having

|-多使用内部函数提高sql语句效率

|-多使用表的别名

|-使用exists替换in,使用 not exists替换not in

|-尽量使用索引类进行查询

|-sql语句尽量大写.oracle会自动转换成大写

|-** 避免在索引列上进行计算

|-** 避免在索引类上使用not,oracle遇到not就使用全表扫描

|-可以使用>=替换>

|-使用in替换or

|-尽量使用where替换group by

|-** 避免使用消耗资源的操作.如 union

7.数据库的物理组件(物理结构)

Oracle主要的物理文件有三类

 |- 数据文件:存储数据,如数据表中的数据,索引数据

 |- 控制文件:记录数据库结构的二进制文件

 |-在线日志文件:记录数据库的日常操作. 用于故障恢复.

费主要的物理文件

 |-密码文件, 参数文件,备份文件,警告和跟踪文件

8.逻辑结构

Oracle的逻辑组件:数据库->表空间-->段-->区->数据块->模式

表空间是oracle中最大的逻辑组件.一个Oracle至少包含一个表空间,系统默认的就是名为

SYSTEM的系统表空间

表空间是由一个或者多个数据文件组成,一个数据文件只能和一个表空间进行关联.

段:是构成表空间的逻辑结构,段由一组区组成。

区:为段分配空间,区是由数据块组成

数据块:是数据库能够读取,操作,分配的最小逻辑单元

模式:等同于用户,用户所创建数据库对象的总称

你可能感兴趣的:(ORACLE基本语法2021-01-27)