标签:数据库
为什么要用数据库? 文件存储: 1、不易于管理和分析(Linux操作系统下输入ls命令会卡死) 2、不易于共享 3、文件内容不断增大,不易于存储 数据库:用数据结构来管理、存储数据的仓库 DB:Database数据库 DBMS:数据库管理系统 数据库软件:Oracle MySQL db2 sql-server sybase 关系型数据库:由二维表组成 非关系型数据库(NOSQL not only sql): Web 高并发性mongodb redis 关系:二维表 二维表:由行和列组成的表格 行:Record一条记录信息 列:字段(Feild) 属性 SQL:(structured query language 结构化查询语言) Oracle甲骨文 Java sun ---> oracle收购 Mysql my ----> sun(2008年1) ---> oracle(2009年4) db2IBM Sybasesybase C/S数据库 Sql server MS 微软 现在是oracle的天下 Oracle商业(收费)大型数据库个人使用 Sql server Windows 商业(收费) Mysql开源免费 --->收费免费版本(不提供服务) 一般中小型企业用mysql阿里用mysql 移动、联通、电信都用oracle 数据库是以二维表的形式存储数据 数据库客户端:sqldeveloper plsql developer(公司一般用) 查看数据库里有哪些表: select * from all_tables;显示用户有权限看到的所有的表,包括系统表 select *from user_tables;当前用户的所有表 selet *from dba_tables;是管理员可以看到的数据库中所有的表 数据库不难,提升效率难:如双11 SQL:所有数据库基本通用的语言 所有数据库都遵循一套规则 主体语言:Java 脚本: 数据库: 数据结构和算法: 业务知识,业务框架: SQL: DDL:Data Definition Language数据定义语言(操作对象是表) 关键字:CREATE:创建数据库对象 建表 DROP:删表 ALTER:改表结构 TRUNCATE:删除表数据,不删除表结构 DML:Data Manipulation Language数据操作语言(操作对象是表的记录) 关键字:INSERT:插入数据 DELETE:删除数据 UPDATE:修改数据 影响的数据,需要事物控制语句才能生效 eg:一张表里两个字段的值 Update** set coll=**,col=**; TCL:Transaction Control Language事物控制语句 关键字:COMMIT:提交,确定把数据提交到数据库 ROLLBACK:回滚,把影响数据的操作撤销 SAVEPOINT:设置保存点,更有利于回滚到特定的场景 DCL:Data Contro Language数据控制语句(操作对象是用户student) 关键字:GRANT:赋权 REVOKE:回收权限 CREATE USER:创建用户 企业中对权限管理非常严格:允许插数据,不允许删数据 DQL:Data Query Language数据查询语句 关键字:SELECT oracle数据类型: 1、数字类型(只用NUMBER) NUMBER(p,s) P表示总位数 S:表示小数的位数 可正可负,最多位数为38位 INTERGER == NUMBER(38) 例子:NUMBER(7,3)能表示的最大的数:9999.999 2、字符串类型 CHAR(n):固定长度的字符,定长字符串 n可以省略,默认为1 指定n,代表n个字节宽度,即使存储的数据的字节小于n,也占n个字节,其余的补空格 最长只能存储2000个字节 VARCHAR2(n):变长字符串 N表示字符串最大的长度 Varchar2(100)只存储10个字符,实际上字符串占的内存和它自身长度是一致的 如:varchar2(100) hello存储5个字节 节省内存 最长能存储4000个字节 LONG:2GB CLOB 3、时间类型 DATE 默认‘DD-MON-YY(RR)’ Systimestamp 时间辍 (时间毫秒) Sysdate 系统时间 DDL: CREATEcreate 建表: Create table table_name( 字段名1 字段类型, 字段名2 字段类型, .... ); 自动提交,不用COMMIT all_tables:记录数据库所有的表 //owner属有者,拥有者 Table_name:表名 user_tables:记录当前用户下所有的表 //dba_tables:记录所有的表,包括系统表(现在不讲) 约法三章: 1、同一个数据库,同一个用户下,只能有唯一的标识符,同名的表只能有一个; 2、不要用别人的表; 3、自己建了之后记得删掉 Sql语句除了字符串里的内容,都要是英文的 创建表:create table ly_student( name varchar2(20), id number(12), gender char(1), birth date ); Number:默认38位 查看表结构:desc wly_student; 能够查看表的所有字段以及字段类型 往里面插入数据: Insert into table_name(字段名) values(值); 字符串用单引号表示 ’ ’ 日期:to_date(‘2017-08-02’,’YYYY-MM-DD’) alter session set nls_date_format = ‘yyyy mm dd hh24:mi:ss‘; select sysdate-1,sysdate,sysdate+1 from dual; 查找昨天,今天,明天这一时刻的时间,按指定格式输出 插入: insert into ly_student(name,id,gender,birth) values(‘龙’,001,’M’,to_date(‘2017-08-02’,’YYYY-MM-DD’)); 精度或者位数超长,报错! Commit;//插入后要提交 EMPLOYEE_ID NUMBER Primary Key:主键(唯一非空:值不能有重复) 当前面赋值过的值,后面再次被赋值时,会报错,必须赋值 查看表的内容:seletct * from wly_student; comment on table ly_student is ’student information’; comment on column ly_student.name is ‘student name’; comment on column ly_student.id is ‘student id’; comment on column ly_student.gender is ‘student gender’; comment on column ly_student.birth is ‘student birth’; 完整的建表语句: 建表的sql脚本及表和字段的详尽说明 =============================================== drop:删除表 drop table ly_student; 按照表名查找特定的表: select * from user_tables where table_name like ‘%LY_STUDENT&‘; like ‘%LY_STUDENT&‘ 可以换成=table_name 需要注意的是:表名大写 drop table ly_student; create table ly_student( name varchar2(20), id number(12), gender char(1), birth date ); Alter table table_name add(字段名 字段类型); alter table ly_student add(address VARCHAR2(100)); Alter table table_name drop column字段名; Alter table table_name drop column address; 删除字段时,要逐行删除该字段的数据,当数据量较大时,效率会比较慢 Alter table table_name modify(字段名 字段类型); Rename old_table_name to new_table_name;修改一个表的名字 模型 DDL语句 CREATE drop alter 提交DB变量 流程,提供 建表: 1、emp:员工表 id:员工idnumber(5) first_namelast_name varchar2(20) Gender性别char(1) birth 生日date hiredate 入职时间date Deptid 部门idchar(2) 2、Dept表:部门表 Id:部门idchar(2) Name:部门名称varchar2(40) 插入三个部门,每个部门插入若干员工 建表加复制数据 Create table table_name as select * from other_table_name; *表示复制所有字段 Create table table_name as select id,name from other_table_name;可以 Create table table_name as select id*2,name from other_table_name;不可以(因为other_table_name里面没有“id*2”这个字段名) 表名不区分大小写 修改字段的类型,(如果有记录可能报错) Alter table table_name modify column_name type; 修改字段的名字 Alter table table_name rename column old_column to new_column DML:(所有操作只有不commit,都可以通过回退,得到原来的数据) Insert into table_name(字段名) values(值); csex CHAR(6) check(csex=‘男‘ OR csex=‘女‘),//如果插入数据不是男或者女,会报错 如果插入全表的字段,table_name后面可以省略字段名; 如果是指定插入某些字段,或者值的顺序和字段名的顺序不一样,则需要字段名和值一一匹配。 修改字段的值: Update table_name set 字段名1=值1,字段名2=值2; 全表所有记录的该字段的值都被修改了 Update table_name set 字段=值 where condition; 不带where条件的update请慎重! 删除记录: Delete [ from ] table_name; 全表的数据被删除,不带where条件的delete请慎重! 删除指定数据:Delete [from] table_name where condition; Truncate:清空表数据,不会对表结构造成影响 Truncate table table_name和delete table_name 都可以把表里的数据全部清空(删除) 1、truncate 不可以带条件,delete可以有 2、Truncate 删除数据不可以修复,delete可以通过rollback将删除的数据回复回来(如果commit了,则回退不了) 3、Truncate效率非常高,delete效率比较慢,如果实际中需要清空一张表,优先选择truncate TCL:(transaction) Commit:提交 Rollback:执行DML语句之后,只要没有commit;都可以回退;但是如果执行了commit,再去rollback都无法回退。 DQL:select Select * from table_name; *代表所有字段都显示,查询tabble_name所有字段的所有记录 Selete 字段1,字段2,...from table_name 查询指定字段的信息 字符串函数:concat ||拼接字符串 Concat(char1,char2) concat可以连用 注意转义字符 ’ select concat(first_name,last_name) from ly_emp; //拼接 select first_name||‘ ‘||last_name name from ly_emp; //拼接,中间加空格 select first_name||‘‘’‘||last_name name from ly_emp; //拼接,中间加 ’ dual 测试表 Length:求字符串的长度 char类型的长度是固定的,varchar2是根据字符串的长度 Lower:将字符串小写 Upper:将字符串大写 Initcap:首字母大写,其余小写 Trim(c1 from c2):把字符c1从字符串c2两端去掉 Ltrm(c1 c2):把字符c2从字符串c1左边去掉 Rtrim(c1,c2):把字符c2从字符串c1右边去掉 Lpad(char1,n,char2):把char1填充为n个字节,在左边补char2 如果n小于length(char1),则会截断,右边截断,剩下左边 Rpad:与lpad相反 select rpad(‘abcd‘,7,‘*‘) from dual; ---> abcd*** translate(char1,char2,char3);把字符串char1里面和char2相同的字符,变成char3 select translate(‘hello‘,‘le‘,‘WX‘) from dual; ----> hXWWo replace(char1,char2,char3):把char1中的char2子字符串换成char3字符串,如果没有char3,则表示去掉char2子字符串部分; Substr(char1,n,m)从字符串char1中,从第n个开始截取,截取m个字符 n=0(或1)表示从第一个字符开始截取,n<0表示从末尾倒数第n个开始,-1表示最后一个字符 Instr(char1,char2,n,m) 在char1中匹配char2,从第n个字符开始,匹配第m个,返回下标 如果匹配不到,返回0 Ascii(char1):求字符串char1第一个字母的ASCII码值 Number函数: Round(n,m):m>0,表示保留m位小数,四舍五入 m<0,表示保留m+1位数字,四舍五入 select round(123.23,-2) from dual;------> 100 Trunc(n,m):和round是一样,但方法不一样,直接舍弃 Ceil(n):向上(大的)取整select ceil(-125.56) from dual; ---> -125 Floor(n):向下(小的)取整select floor(-125.56) from dual; ---> -126 Mod(n,m):取余n%m:当m=0时,直接返回0 函数可以直接作用于字段 Emp(salary number(8,2) ); Select salary*12 from number; To_date();按格式把字符串转换成一个日期 YYYY ---> 年; MM---> 月 ; DD ---> 日; Mon--->英文的月份;day --->星期几(1表示日) HH ---> 小时; HH24 ---> 24小时制;mi --->分钟;ss ---> 秒 Add_month:select add_months(birth,3) from ly_emp;所有月份加3 Last_day():select last_day(birth) from ly_emp;返回月的最后一天 Months_between(a,b):select months_between(birth,hiredate) from ly_emp; //两个日期相差的月份 Next_day():select next_day(sysdate,1) from dual;//下周的星期日的日期To_char():可以把时间和数字转换成字符串 select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss‘) from dual;将当前时间转化成指定格式 Trunc Round Select:查询数据库的数据 单表查询: 1、查询所有字段所有记录:select * from 表名 2、查询指定字段所有记录:select字段,... form 表名; 3、可以给字段取别名: Select 字段 字段别名,... from 表名 4、可以用字符串、数字、日期函数对字段进行处理 5、Select可以带条件用where来过滤数据 1、指定字段的值 where 字段=值 2、指定字段的值在某个区间,数字的值可以通过< 和 >来匹配, < > != 来匹配不等于某个值的数据 可以用and来连接两个有表达式,表示两个表达式都满足的情况下的所有记录 可以用or来连接两个表达式,只要满足其中之一的表达式则匹配 Select * from table_name where id=1; Select*from table_name where sal <> 800(或者sal !=800) Select * from table_name where sal>800 and sal<1800; 3、字符串 可以用= 和 != 来匹配; 模糊匹配:like % 匹配任意多个任意字符 _ 能够匹配任意一个字符 Select*from emp where ename like ‘A%’;把名字是以A开头的匹配出来 Select*from emp where ename like ‘_A%’;匹配第二个字符是A的 匹配以A开头或者S结尾的名字: Select*from emp where ename like ‘A%’ or ename like ‘%s’; 4、between and 相当于 字段 <= ** and 字段 >=** Select * from table_name where sal>=800 and sal<=1800; Select * from table_name where sal between 800 and 1800; 5、in 来匹配零散的值 Select * from table_name where sal in(1250,800,1300);匹配工资为这三个值的数据,括号里可以有多个值 Select * from table_name where sal not in(1250,800,1300);匹配除了这三条的其他数据; In(list) 用表的记录来list里面进行逐一比较(=),如果相等,则匹配该条记录;List里面如果有null,null匹配不出来 Not in(list) 用表里的记录来list里逐一进行比较(!=),如果全部都不相等,则匹配该记录;表中null的记录匹配不出来 Not in(list)所有值都不等于list里面的值才匹配,null只要list里面有null值,not in(list)将没有一个被匹配出来。 例子:建表时:给默认值default设置默认值 字段非空:not null表示不为空 Create emp(id number(10) not null,//不插入数据,报错 Name varchar2(20),//不插入数据,为null Gender char(1) default ‘F’//不插入,默认为F ); 插入数据时,如果该字段没有值,默认为null,但是如果该字段是not null,则插入失败,非空字段一定要有值存在 Null值在oracle中非常关键 Null:是一种特殊的值,空值 任何数据类型都可以是空值 一个字段的值未确定或者没有必要时可以为null; Null值不可以用= 和 !=来进行比较判断 select * from emp where mgr is (not)null; 空值处理函数 Nvl(expr1,expr2) 如果expre1为空,则取expr2的值 如果expr1不为空,则取它自身的值 select empno,ename,(nvl(comm,0)+sal)*12 from emp; Nvl2(expr1,expr2,expr3) 如果expr1为空,则取expr2的值 如果不为空,则取expr3的值 select empno,ename,(nvl(comm,comm,0)+sal)*12 from emp; 给字段取别名会自动变成大写的,如果想保持原状,可以用双引号“”; 如果别名需要空格,也可以用双引号“” 可以给字段取别名,用as关键字,但as可以省略 select empno,ename,(nvl(comm,0)+sal)*12 “salary” from emp; 查找所有的部门emp: 去重:去除重复的没必要的数据 distinct Distinct可以对单个字段去重,也可以对多个字段一起进行去重 select distinct deptno,job from emp; //查找每个部门都有哪些岗位 排序: Order by 字段asc/desc 升序/降序 默认是按升序排序,所以asc可以省略 //查找所有的员工,按部门升序显示所有的员工的薪资从多到少 select * from emp order by deptno asc , sal desc; 对多个字段进行排序时,先按前面的字段进行排序(分组),然后再按后面的字段进行排序,注意:每一个字段都要指定排序方式(asc/desc,asc可以省略(默认值));order by和distinct只出现一次。 Null最大,asc排序,null排在最后面 日期: 要对日期进行判断 select sysdate +1 from dual;系统时间加n天 select trunc(sysdate,‘dd‘)-to_date(‘2017-01-01‘,‘yyyy-mm-dd‘) from dual;截取系统时间到天,距离2017-1-1日的天数; 日期可以直接加减运算,也可以用<,>,<=,>=,=,!=来判断两个日期 To_char() 整数按格式转换为字符串 格式字符串里以fm开头 9 代表任意一个数字 0 强制显示前导0,如果该位置有数字,则显示数字,数字不足则显示0 . 代表小数点 $ 代表美元符号 L 代表本地货币符号 select to_char(123.34,‘fm09999.99‘) from dual; ==》00123.34 select to_char(123.34,‘fm99.99‘) from dual; ==》###### select to_char(123.456,‘fmL999.999‘) from dual; ==》¥123.456 select to_char(123456.456,‘fm$999,999.999‘) from dual; ==》$123,456.456 聚合函数: 对数据进行分组,然后进行统计工作 一个组返回一条记录 分组函数,集合函数 Max:select max(sal) from emp;//找到sal最高的员工 Min:select min(sal) from emp; select max(sal) max_sal,min(sal) min_sal from emp;//找到并重命名 可以用于number,char,date类型 过滤掉记录里的null值 Avg sum 平均值 和值 1、求所有员工的平均工资select avg(sal) avg_sal from emp; 2、求公司一个月要发放的工资select sum(sal+nvl(comm,0)) from emp; Avg sum只能用于number,自动过滤掉null 3、平均奖金 select avg(nvl(comm,0)) from emp; Select avg(comm) from emp;求有奖金员工的每个人的平均奖金 Count求记录的数目 Select count(*) from emp;//emp里面有多少个员工 Select count(1) from emp;//计数所有的记录,可以随便填 Select count(ename) from emp;//emp里面有多少个名字 Count可以对任意内容进行统计,会自动过滤掉null值 1、每个部门里工资最大、最小 select deptno,max(sal),min(sal) from emp group by deptno; 2、统计每个部门的平均工资和工资总和 select deptno,avg(sal),sum(sal) from emp group by deptno; 3、每个部门有多少员工 select deptno,count(1) from emp group by deptno; 分组: Group by 字段 组函数自动过滤null记录 1、查找部门编号大于10的部门的员工平均工资 Select avg(sal) from emp where deptno>10; 2、查找部门编号大于10的部门平均工资:先过滤数据然后再组函数 Select avg(sal) from emp where deptno>10 group by deptno; 3、查找部门平均工资大于1600的部门编号及其平均工资:先用组函数求值(分组),然后再过滤数据 Select deptno,avg(sal) from emp group by deptno having avg(sal)>1600; Having:用来过滤分组数据,只能用在group by之后; SQL语句的执行顺序: 1、from语句:从右往左,从后往前执行,建议把数据量少的放后面,数据大的表放前面; 2、Where语句:从右往左,从下往上执行;建议把过滤数据量多的语句放后面; 3、Group by语句:非常消耗资源,建议少用;建议在where的时候尽量过滤多的数据; 4、Having语句:从左往右 5、Select语句:oracle在解析*的时候,会先根据表名去查找这个表的字段(解析字段),需要消耗时间,所以尽量避免使用*,而是用具体的字段替代; 6、Order by语句:从左往右,非常耗资源。 多表查询: 1、显示员工编号、员工姓名、员工所在部门编号及部门名称 关联查询 select * from emp;//14条数据 Select * from dept;//4条语句 Select * from emp,dept;//56条数据 笛卡尔积:两个表数据的记录相乘得到的就是笛卡尔积 等值连接 Select empno,ename,emp.deptno,dname from emp,dept where emp.deptno=dept.deptno 多表查询: 多个表之间用逗号隔开;如果两个表有同名的字段,需要显示同名的字段时,需要表名.字段名来区别,对于表,也可以有别名 Select e.empno,e.ename,d.deptno,d.dname From emp e,dmpt d Where e.deptno=d.deptno; 内连接:把等值连接中表名之间‘,’换成join,再把where换成on; Select e.empno,e.ename,d.deptno,d.dname From emp e join dept d On e.deptno=d.deptno 外连接: 左外连接:left join左边表里的数据一条都不会少(全部匹配),左边表也称为驱动表,然后根据条件去右边的表匹配,匹配不上的记录,该表的字段自动填充为null值。 Select e.empno,e.ename,d.deptno,d.dname From emp e left join dept d On e.deptno=d.deptno; 也可以写成:Select e.empno,e.ename,d.deptno,d.dname From emp e ,dept d Where e.deptno=d.deptno(+); //(+) 一定写在驱动表的对面 右外连接: Select d.deptno,d.dname,e.empno,e.ename From emp e right join dept d On e.deptno=d.deptno; 也可以写成:Select d.deptno,d.dname,e.empno,e.ename From emp e , dept d Where e.deptno(+)=d.deptno; 全外连接: Select d.deptno,d.dname,e.empno,e.ename From emp e full join dept d On e.deptno=d.deptno; 自连接:对同一张表用别名的方式扩展为两张表,然后再进行关联匹配 select distinct e1.empno,e1.ename from emp e1 , emp e2 where e1.empno=e2.mgr; 记住:外连接有个关键字outer;left outer join Sql高级查询: 条件、表可能是从一个select语句中获得 Select语句作为where的子句: 可能where依赖的条件不是一个确定的值,也不是通过函数求得;依赖于一条select的返回值 select语句中嵌套一个select语句,这个嵌入的select语句称为select子句 Select 子句先执行,得到结果之后,再进行父select比较 根据select语句的返回值,可以分为: 单行select子句(= in < > != ...) 多行select子句(ANY ALL in not in) 多列select子句(in) Select语句:返回一行数据,多行数据,多列数据 返回多条语句: ANY,ALL函数,不能单独使用,只能和< > <= >= 一起使用 <ANY( list ) 小于其中一个 <ALL( list ) 小于所有的 Exists:(用的很多)用在where条件中,对于exists里面如果有返回记录,则表示条件为true,否则返回false Select语句作为from的子句: From的目标是一个表,当用select语句作为from的目标时,select子句称之为行内视图,或者匿名视图 Rownum: 用来标识表里数据,用数字对所有的记录进行编号,编号从1开始,全部连续,也称之为伪列; 用了之后,会出现一条标记行号的一列,但是访问只能从1开始,不能从中间开始或直接访问后面的; 可以把一个select出来的rownum当做一个行内视图,把rownum取一个别名,这时候伪列就变成真的字段 Oracle的分页记录:rownum Decode(expr[,expr1,result1[,expr2,result2]][,default]) 集合操作:对分表时非常重要 Union结果是并集:a+b-重复的 union all结果是a+b, Intersect并集 Minus a-重复的(不会为负的) 对多个select语句的结果进行集合操作 每一个select语句的字段个数、顺序和类型必须相同 Rownum 分组函数: Row_number() over(PARTiTION BY col1 ORDER BY col2【,col3 desc】) 返回一个和rownum相识的东西(编号) 对coll字段进行分组,然后再对col2进行排序 编号从1开始,连续且不重复,也不能直接截取 Rank() Rank( ) over(PARTiTION BY col1 ORDER BY col2【,col3 desc】) 对coll字段进行分组,然后再对col2进行排序,编号从1开始,如果排序值相同,然后会跳跃,如果两个并列第二,后面从第4开始 Dense_rank() Dense_rank() over(PARTiTION BY col1 ORDER BY col2【,col3 desc】) 对coll字段进行分组,然后再对col2进行排序,编号从1开始,如果排序值相同,则编号相同,不会跳跃,如果两个并列第二,后面从第3开始 高级分组: 按年统计销售额 按月统计销售额 Group by rollup(a,b,c) 按a,b,c A,b A Group by cube(a,b,c) Group by grouping sets((a),(b)...) 小括号里填分组的字段 指定需要的分组,显示数据 约束 条件约束 为了维护数据的完整性及逻辑性 用约束来限制(DML insert update delete)表里的数据 非空约束(NOT NULL) 简写 NN 唯一约束(UNIQUE) 简写UK 主键约束(PRIMARY KEY) 简写 PK 外键约束(FREIGN KEY)简写 FK 检查约束(CHECK) 简写 CK 默认值(default) 这不是约束 约束可以在建表时指定,也可以在建表之后添加 所有的约束都在 user_constraints表中 1、非空约束 Insert时,如果有字段为not null,那么一定得插入该字段的值,否则会报错;update时,无法将该字段更新为null。 什么时候用:为了确保该字段一定有值 在建表之后添加非空约束 Alter table wly_stu add constraints constraints_name check(id is not null); 其中id是一个字段 删除约束 Alter table wly_stu drop constraint constraints_name 改变非空属性 Alter table wly_stu modify (id number(7) not null) 添加非空约束 Alter table wly_stu modify (id number(7) null) 删除非空约束 如果是匿名约束,需要先去user_constraints表中找到相应的约束,以及默认的约束名,然后再把它删除 2、唯一约束: 值唯一,不能重复 建表时建唯一约束 create table wly_stu( id number(10) , name varchar2(30) not null, gener char(1) constraint id_constraint_uk unique(id)//id字段有唯一约束,不能插入两个相同的值 (null值例外,可以有多个id为null的行) ); 建表之后添加唯一约束 Alter table wj_stu add constraint constraint_name unique(coll); 唯一约束可以是一个字段也可以是多个字段,多个字段时表示只要有一个字段不相同即为不相同 Alter table wj_stu add constraint constraint_name unique(id,name); Insert into wj_stu values(110,’’xiaohong’); Insert into wj_stu values(110,’xiaohei’);这两条都可以插入,如果完全相同,则不能插入 3、主键约束: 必须非空,且值唯一 一个表里,主键约束只能有一个 一个表里,约束只能 主键约束可以提升select效率很好,(数据量多,根据主键查询时) 主键约束也可以是对组合字段,但不建议 主键约束建在什么地方,什么字段建主键? 1、主键字段不要有具体的逻辑业务 2、主键约束不要经常DML操作 3、主键值应该自然有序,用序列生成最好 4、主键相当于索引 4、外键约束: 多张表之间的关系,一张表的字段的值依赖于另一张表的字段的值 被依赖的表叫做:主表 依赖其他的表叫做:从表 在建表时建外键约束,得先建主表,再建从表(建外键约束) Alter table wj_dept add constraint constraint_name primary key(deptno) Alter tbale wj_emp add constraint constraint_name foreign key(deptno) references wj_dept(q_dept); Create table ly_dept( //主表 Deptno number(2) primary key, //主键 Dname varchar2(30) not null, Loc varchar2(30) ); Create table ly_emp( //从表 Empno number(2) primary key, Ename varchar(30) not null, Deptno number(2), Constraint constraint_name foreign key(deptno) references ly_dept(deptno) //依赖于主键关系,外键约束 ); 外键约束:主表列是主键,从表添加不需要add关键字 外键约束对性能非常损耗,在从表插入数据时,要去主表里查询是否有对应的值,不建议使用, 除非特殊情况 可以不用外键约束来限制数据的完整性,这部分功能可以在代码里实现 索引、视图 从表里外键约束的值可以插入null值,除了空值以外的值,只能是主表里对应的值(主表里有的值) 从表里引用了主表里的值,则主表里的值不允许删除或者修改 Insert into ly_emp(empno,ename,deptno) values(120,’long’,20); Delete ly_dept where deptno=20;//错误的,在从表里引用了 增加外键: Alter table tbale_name add constraint constraint_name foreign key(col) references other_table_name(other_col) create table parent (c1 number(2) primary key); child表的c2列为外键,引自parent表的c1列 方法一:create table child (c1 number(4) constraint child_c1_pk primary key, c2 number(2) constraint child_c2_fk references parent(c1)); 方法二:create table child (c1 number(4) constraint child_c1_pk primary key, c2 number(2) ,constraint child_c2_fk foreign key(c2) references parent(c1)); 5、检查约束: 对数据进行检查,只有满足条件的情况下才允许插入和修改 Check(条件) Check(gender in(‘男’,’女’))//插入数据时只能是男或者女,否则报错 Alter table wj_emp add constraint constraint_name check(id>1000 and name like ‘%A%’); Insert into wj_emp values(110,’wng’,20);//报错 Insert into wj_emp values(1110,’wang’,20);//不会报错 非空约束 not null 唯一约束 unique 可以往里插入多个null值 主键约束 不可以为空 外键约束 可以插入空值 检查约束 只要不检查是否为空,那就可以插入null值 可以在建表时建立约束,也可以在建表之后添加、删除 Alter table table_name add constraint constraint_name *** Unique(col) Primary key(col) Foreign key(col) references table_name(col) Check(condition) User_constraints 保存着用户下所有的约束名(如果创建时没有指定约束名,系统会 自动生成一个约束名) 视图:把一个select语句的结果集当做一个表一样使用,虚拟的表,是数据的逻辑表示,其本质 是一个select语句加了一个名字 创建一个视图 Create [or replace] view view_name as subquery; Subquery:一个select语句 试图分为: 1、简单视图:select 语句包含一张表,但是没有有函数、表达式、group by的约束 2、复杂视图:select 语句包含一张表,但是有函数、表达式、group by的条件 3、连接视图:select 多张表 Create view emp_view_20 as select empno,ename,deptno,sal from emp 创建视图需要权限:grant create view to 用户(student); 所有的视图名都保存在User_views里 视图是一个select语句的结果集,他没有具体的数据,而是一种映射关系。当视图建立以后,可以 把试图当做一张表一样使用(select) 视图作用: 1、对于复杂的select语句,建立视图之后,可以提升查询效率 2、通过视图只能查询特定的记录和字段,能够隐藏和保护一些数据及字段,保护数据和屏蔽 数据的作用(安全措施) 3、操作视图就等于操作视图映射的表。(不建议通过视图修改表里的数据),可以在创建视图时 指定视图只能查询,不能修改数据 在创建视图的语句后面加With read only; 对于复杂的视图,根本就不允许插入和删除。 Create view emp_view_20 as select empno,ename,deptno,sal from emp where deptno = 20; 当插入部门不是20的数据时,视图不会有变化,但是映射所对应的表会多一行数据;当修改一个 deptno为20的数据变成不是20时,视图里会消失。 可以通过限定用户智能操作视图里有的数据: with check option—— DML只能操作视图里有的数据(只对视图可见) Delete时只能删除视图里有的数据 Insert时只能插入满足select条件的数据 Create or replace view 可以创建和修改视图 Drop view view_name 删除视图 在用函数和表达式进行创建视图时,必须用别名 Create view emp_view_20 as select empno,lower(ename) name,deptno,sal from emp 序列:(sequence)可以自动生成数字值的数据库对象 CREATE sequence seq_name [ start with i ] [ increment by i ] [ minvalue n|no minvalue] [maxvalue m|no maxvalue] [cycle | nocycle] [ cache p | on cache]; Start with i表明从i开始计数 Increment by j 表明每次递增多少(j是负数,递减) 如果没有指定i和j,从1开始递增,每次递增1 Cycle:表明值取到了最大值之后,可以从最小值开始重新开始计数 如果是取到了最小值,可以从最大值重新开始计数 Cache p:表示每次生成多少个数字,缓存的值的个数,默认是20 序列可以有效的用来生成主键的值 多个表可以共用一个序列,但是建议一个表用一个序列 user_sequences所有的序列都存储在这个表里 Nextval:获取序列的下一个值,每执行一次nextval会增长一次,在序列刚创建时, 必须使用一次nextval才能使用currval Currval:获取序列的当前值 Create sequence seqly_emp2 Start witn 1000 increment by 1 Minvalue 1 maxvalue 1000000000 nocycle cache 2000 create table wly_emp_test( id number(10) primary key, name varchar2(30) ); select seqly_emp2.nextval from dual; insert into wly_emp_test(id) values(seqly_emp2.nextval); select * from wly_emp_test; 序列可以高效的用来生成主键的值 删除:drop sequence seq_name; 索引: Rowid是一个伪列,用于标识数据表里每一条记录的地址 Pl sql developer里面:select e.*,e.rowid from emp e;可以在表中直接修改 索引是保存记录的地址及索引关键字,用于提升查询效率最有效的方法 字典:通过目录去查找 视图:把内容大的拆分成每一块内容较小的,再去查找 Create index [unique] index_name on table_name(col); 注意事项: 1、数据量小的时候应该避免建索引 2、一般给where条件,group by 这些经常用来查询的字段建索引 3、索引的个数没有限制,但不是越多越好 4、索引对于查询的效率有很好的提高,但是得建立合适的索引 5、索引也是占用资源的(需要保存值和地址) 6、二叉树 oracle实现索引是用二叉树:B-tree 7、对于经常DML操作的列,应当根据情况避免建索引,因为索引会影响insert操作的执行效率 删索引 --> 导数据 --> 再建索引 会比直接导数据的效率要高 Create index deptno_index on dept(deptno); User_objects;---索引、视图、序列均可在这个表里查到 索引一旦建立之后,oracle自动维护,查询时不需要指定使用哪个索引 Select * from emp where empno =** ---empno Select * from emp where ename =** ---ename 如果某个字段的值是唯一的,可以建唯一索引 Create unque index empno_index on(empno); 如果索引字段的值经常DML,可以用Alter index index_name rebuild; 更新索引,将删除的数据的索引删掉,提高内存效率 索引:建在那个字段,经常用来查询数据的字段,这个字段可以是组合字段,group by deptno,mgr -------> On(deptno,mgr); 在生产中,索引用的非常多 索引:用空间换时间,消耗内存空间提升效率
本文出自 “Java学习” 博客,请务必保留此出处http://12181171.blog.51cto.com/12171171/1962674
标签:数据库
原文地址:http://12181171.blog.51cto.com/12171171/1962674