SQL基础

ORACLE

	|-入门语句
			|-数据库连接
					|-普通用户连接:Conn scott/tiger
					|-超级管理员连接:Conn sys/sys as sysdba
					|-断开连接:Disconnect
			
			|-SQL操作
					|-保存SQL文件:Save c:\1.txt
					|-编辑SQL语句:Ed c:\1.txt
					|-运行SQL语句:@ c:\1.txt
					|-显示表结构:Desc tableName;
					|-查看用户下的所有对象: Select * from tab;
			
			|-系统表操作		
					|-查询指定名称表信息:select owner, object_name, status from dba_objects where object_name like '%DUAL%'		
					
					
	|-单行函数 
			|-字符函数
					|-Upper
					|-Lower
					|-Initcap
							|-将字符串首字母变成大写
					|-concat
							|-concat('a', 'b')= 'a'||'b' --> 'ab'
					|-substr
							|-substr( string, start_position, [ length ] )
					|-replace
							|-replace('Abc', 'a', 'A') --> 'abc'
					|-instr
							|-instr(源串,目标串[,开始位置[,第几次出现]])		
					|-lpad/ rpad
							|-lpad(源串,数量,数量不足的时候填充的字符串);
							|-select lpad('yao', 10, 'fuck') from dual; --> 'fuckfucyao'
					|-trim
			|-数值函数
					|-Round
							|-ROUND(指定数值, 指定位数)
									|-例:select round(412, -2), round(412.313, 2) from dual; --> 400, 412.31
					|-Mod
							|-Mod(n1, n2) --> n1%n2
					|-Trunc
							|-意为截断,不进行四舍五入操作
									|-日期型
										|-select trun(sysdate, 'mm' from dual;	--> 01-7月 -12
										|-select trun(sysdate, 'dd' from dual;	--> 23-7月 -12
									|-数值型
										|-select trunc(89.986, 2) from dual;	-->	89.98
			|-日期函数
					|-Months_between
							|-select sysdate, to_date('20120612', 'yyyymmdd'), months_between(sysdate, to_date('20120612', 'yyyymmdd')) from dual; -->	1.38223118
					|-Add_months
							|-select sysdate, add_months(sysdate, 1) from dual;	--> 	2012-07-23, 2012-08-23
					|-Next_day
							|-下一个指定星期:select sysdate, next_day(sysdate, '星期四') from dual;	-->	2012-07-23 星期一, 2012-07-26 星期四
					|-last_day
							|-该月最后一天:select last_day(sysdate) from dual;	-->	2012-07-31
			|-转换函数
					|-to_char
							|-to_char(sysdate, 'yyyy')	-->	2012
							|-to_char(sysdate, 'fmyyyy-mm-dd')	-->	2012-07-23
							|-to_char(111.1, 'L999, 999, 999')	-->	¥999
					|-to_number
							|-select to_number('13')+ to_number('14') from dual;
					|-to_date
							|-select to_date('20120723', 'yyyymmdd') from dual;
			|-通用函数
					|-NVL
							|-空值时设置为默认值:select nvl(null, 0), nvl(111, 0) from dual;	-->	0, 111;
					|-NULLIF
							|-相等返回NULL,否则返回第一个值:select nullif(0,0), nullif(11,12) from dual;	-->	null, 11;
					|-NVL2
							|-值1为空返回值3,否则返回值2:select nvl2(null,1,2), nvl2(1,1,2) from dual;	-->	2, 1
					|-CLALESCE
							|-返回第一个非空值,参数为同类型(!!)无限数量:select coalesce(null, null, 1, null, 2) from dual;
					|-CASE
							|-select empno, ename, case deptno when 1 then '财务部' when 2 then '外交部' when 3 then '开发部'	else 'FBI'	end as 部门 from emp;
					|-DECODE
							|-与CASE一般用途:select empno, ename,decode(deptno, 1,'财务部', 2, '外交部', 3, '开发部', 'FBI') as 部门 from emp;
							
							
	
	
	|-多表查询
			|-笛卡尔集
					|-select * from emp, dept;
			|-等值连接
					|-select dname, ename, hiredate from emp, dept where emp.deptno= dept.deptno;
			|-非等值连接
					|-笛卡尔集的基础上进行条件判断:select ename, empno, grade, sal, losal, hisal from emp, salgrade where sal between losal and hisal;
			|-自连接
					|-select e.ename, m.empno from emp e, emp m where e.mgr= e.empno;
			|-左外联接
					|-select s.sname, t.tname from student s, teacher t where s.ssex= t.tsex(+)
					|-select s.sname, t.tname from student s left join teacher t on s.ssex= t.tsex
			|-右外联接
			|-满外联接
					|-select s.sname, t.tname from student s full outer join teacher t on s.ssex= t.tsex
					
	|-集合操作
			|-UNION
					|-并集,显示所有,但重复项只显示一次
			|-UNION ALL
					|-并集,显示所有,包括重复项
			|-INTERSECT
					|-交集,只显示重复项
			|-MINUS
					|-差集,只显示对没有的,与顺序有关
					


	|-子查询
			|-单行子查询
					|-select * from student where sage >(select sage from student where sid= 80308100);
					|-子查询结果为空时无返回结果
					|-子查询返回多行时报错
			|-多行子查询
					|- SELECT * FROM TABLEA WHERE FLD > ALL(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD > (SELECT MAX(FLD) FROM TABLEA)
					|- SELECT * FROM TABLEA WHERE FLD > ANY(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD > (SELECT MIN(FLD) FROM TABLEA)
					|-  SELECT * FROM TABLEA WHERE FLD = ANY(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD IN (SELECT FLD FROM TABLEA)
			|-分页查询
					|-select * from (select rownum no, e.* from (select * from emp order by sal desc) e where rownum<= 5) where no>= 3;
			|-EXISTS
					|-select * from student s where exists (select null from teacher t where t.tage> 2* s.sage);
					|-注意事项
							|-子查询记录少,主查询表大且有索引时用IN,反之用EXISTS
							
							
	|-高级查询
			|-随机返回指定数量的记录
					|-SELECT * FROM (SELECT * FROM student ORDER BY dbms_random.value()) WHERE ROWNUM<= 2;
			|-排序的时候进行空值优先顺序
					|-SELECT * FROM student ORDER BY sname NULLS FIRST;
			|-为行指定行标记,不同于行序ROWNUM
					|-SELECT * FROM (SELECT row_number() over (ORDER BY sname) rn, sname FROM student) s WHERE MOD(rn, 2)= 1;
			|-同时查询最大最小值
					|-SELECT MAX(sage) over(), MIN(sage) over() FROM student;
			|-连续求和
					|-SELECT sname, sage, SUM(sage) over(), SUM(sage) over(ORDER BY sname) FROM student;
						|-SUM(sage) over()= SUM(sage),但可用于非聚合语句中
						|-SUM(sage) over(ORDER BY sname),在sname的层次上逐个添加
							|-   	SNAME	SAGE	SUM(SAGE)OVER()	SUM(SAGE)OVER(ORDERBYSNAME)
									1	潘巧容	23		57							23
									2	王老吉	10		57							33
									3	姚清居	24		57							57
									4				 			57    						57
			|-分组求和
					|-SELECT sname, ssex, sage, SUM(sage) over(PARTITION BY ssex ORDER BY sname) FROM student;
						|-   	SNAME	SSEX		SAGE	SUM(SAGE)OVER(PARTITIONBYSSEXO
								1	test		男		99		99
								2	姚清居	男		24		123
								3	female	女		33		33
								4	潘巧容	女		23		56
								5	王老吉	中性	10		10
								6								88		88
			|-得到上行记录和下行记录
					|-SELECT 
								sname, sage, 
								lead(sage) over(ORDER BY sage) nextAge, 
								lag(sage) over(ORDER BY sage) frontAge 
						FROM student;				
			|-根据子串分组
					|-SELECT to_char(tmp_date, 'yyyy'), AVG(tmp_id) 
						FROM temp 
						GROUP BY to_char(tmp_date, 'yyyy');				
			|-确定一年的天数
					|-SELECT add_months(trunc(SYSDATE, 'y'), 12) - trunc(SYSDATE, 'y') FROM dual;
			|-查询每个性别下最年轻的前两位的信息
					|-SELECT * FROM (
						       SELECT sname, ssex, sage, row_number() over(PARTITION BY ssex ORDER BY sage) rn
						       FROM student
						)
						WHERE rn< 3;
					|-SELECT sname, ssex, sage 
						FROM student s1
						WHERE (
						  SELECT COUNT(1)
						  FROM student s2
						  WHERE s1.ssex= s2.ssex AND s1.sname!= s2.sname AND s2.sage< s1.sage
						)< 2
						ORDER BY ssex, sage;
	|-数据字典
			|-查询用户权限表
					|-SELECT * FROM All_Tables WHERE owner= 'YQJ';
			|-查看指定用户拥有的指定表单的所有字段完整信息
					|-SELECT * FROM all_tab_columns WHERE table_name= 'STUDENT' AND owner= 'YQJ';
			|-查询表索引
					|-SELECT * FROM sys.All_Ind_Columns WHERE table_name= 'STUDENT';
			|-查询表约束
					|-SELECT * FROM all_constraints WHERE table_name= upper('student');
			|-查询Oracle中描述数据字典视图
					|-SELECT table_name, comments FROM DICTIONARY WHERE table_name LIKE '%TABLE%';
			
			
	|-Oracle体系结构(DBA)
			|-数据库
					|-一系列物理文件(数据文件,控制文件,重做日志文件,联机日志等)的集合与对应的逻辑结构(表空间、段、区、块等)
			|-数据库实例
					|-内存结构
							|-SGA
							|-PGA
					|-后台进程
	
	
	|-DDL- 改变表结构
			|-建表
					|-自定义表结构
						CREATE TABLE person(
							pID NUMBER(10),
							pName VARCHAR2(30),
							pSex VARCHAR2(10)
						)TABLESPACE yqj;	--不写默认创建在当前用户的表空间上
					|-在已有表基础上进行结构和数据搭建
						CREATE TABLE employ
						AS SELECT 0 AS sel, person.* FROM person;*
			|-新增字段
					|-ALTER TABLE EMPLOY ADD eage NUMBER(5);
			|-修改字段属性
					|-ALTER TABLE employ MODIFY eage NUMBER(10);
			|-修改字段名称
					|-ALTER TABLE employ RENAME COLUMN psex TO esex;
			|-删除字段
					|-ALTER TABLE employ DROP COLUMN test;
			|-清空表数据
					|-TRUNCATE TABLE employ;
			|-表重命名
					|-RENAME employ TO zhiyuan;
					
					
	|-DML- 改变数据结构
			|-插入
					|-INSERT INTO aaa(sid, sname, ssex, sage, saddress)
						SELECT sid, sname, ssex, sage, saddress FROM student WHERE ssex= '中性'
			|-更新
					|-UPDATE aaa
						SET(sname, saddress)=
							(SELECT sname||'2', saddress||'2' FROM aaa WHERE sid= 80308101)
						WHERE sid= 80308100
			|-删除
					|-DELETE FROM aaa WHERE sid= 80308100;
			|-有更没插
					|-MERGE INTO aaa
						USING student	--这个标注了范围
						ON(aaa.sid= student.sid)
						WHEN MATCHED THEN
						UPDATE SET sname= student.sname, ssex= student.ssex, saddress= student.saddress
						WHEN NOT MATCHED THEN
						INSERT(sid, sname, ssex, sage, saddress) VALUES(student.sid, student.sname, student.ssex, student.sage, student.saddress)
						;
			
	|-约束
			|-例
					|-CREATE TABLE constraintExamp(
						 cID NUMBER PRIMARY KEY,
						 cName VARCHAR(30) NOT NULL,
						 cTel VARCHAR2(50) UNIQUE,
						 cAge NUMBER CHECK(cAge BETWEEN 0 AND 150),
						 cCountryID NUMBER REFERENCES country(cCountryID) ON DELETE CASCADE
						);
			|-非空约束
					|-NOT NULL
					|-限制该项不为置空
			|-主键约束
					|-PRIMARY KEY
					|-不能重复,不能为空
			|-唯一约束
					|-UNIQUE
					|-值不能重复,空值除外
			|-条件约束
					|-CHECK
					|-插入数据必须满足特定条件
			|-外键约束
					|-指定该项值取自指定表的列值kwkw
					|-cCountryID NUMBER REFERENCES country(cCountryID)
					|-CONSTRAINT constraintExamp_cCountryID_fk FOREIGH KEY(cCountryID) REFERENCES COUNTRY(cCountryID)
			|-级联删除
					|-主表信息删除后,自动进行关联表的信息清除
					|-ON DELETE CASCADE
			
		|-增加约束
				|-ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cID_pk PRIMARY KEY(cid);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cTel_uk UNIQUE(cTel);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cAge_ck CHECK(cage BETWEEN 0 AND 150);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT country_constraintExamp_cCountryID_fk FOREIGN KEY(cCountryID) REFERENCES country(cCountryID) ON DELETE CASCADE;
		|-删除约束
				|-ALTER TABLE CONSTRAINTEXAMP DROP CONSTRAINT constraintExamp_cID_pk;
		|-启用约束
				|-ALTER TABLE CONSTRAINTEXAMP ENABLE CONSTRAINT constraintExamp_cID_pk;
		|-禁用约束
				|-ALTER TABLE CONSTRAINTEXAMP DISABLE CONSTRAINT constraintExamp_cID_pk;
				
				
				
	|-视图
		|-概念:封装了各种复杂查询的语句
			|-创建视图
					|-CREATE VIEW 视图名称(字段) AS 子查询
					|-CREATE OR REPLACE VIEW maleStudent (sid, sname, ssex, sage, saddress)
						AS 
						SELECT sid, sname, ssex, sage, saddress
						FROM student
						WHERE ssex= '男'
						WITH CHECK OPTION CONSTRAINT maleStudent_ck;
						--WITH READ ONLY;
			|-更新视图
					|-UPDATE maleStudent SET ssex= '';
					|-注意会联动更新原表记录
			|-保护视图的创建规则
					|-保护WHERE语句中的字段不被修改
					|-WITH CHECK OPTION CONSTRAINT maleStudent_ck
			|-只读
					|-设置任意字段都不可更改,视图为只读
					|-WITH READ ONLY
			|-查看视图
					|-SELECT * FROM maleStudent;
			
			
			
	|-索引
			|-定义
					|-用于提升查询效率的数据库对象
					|-通过快速定位数据的方法来减少磁盘I/O操作
					|-索引信息与表独立存放
					|-Oracle数据库自动使用和维护索引
			|-分类
					|-唯一性索引
					|-非唯一性索引
			|-创建方式
					|-自动创建
							|-在定义主键和唯一键时系统自动在相应字段上创建唯一性索引
					|-手动创建
							|-用户选择在其它列上创建非唯一索引,以加速查询速度
			|-查询方式
					|-查询现有的索引信息:SELECT * FROM user_indexes;
					|-查询索引建立在哪些字段上:SELECT * FROM user_ind_columns;
			|-优缺点
					|-优点
							|-极大加快数据的检索速度
							|-创建唯一性索引,保证数据库中第一行数据的唯一性
							|-加速表和表之间的连接
							|-使用分组和排序子句进行检索时,明显减少查询速度
					|-缺点
							|-索引需要占用物理空间
							|-当对表中数据进行增删改时,索引亦需动态维护,降低数据维护速度
			|-创建原则
					|-select占多的表上
					|-where语句中出现频率最高的列
					|-小于5M的表,最好不要使用索引查询,表越小越适合用全表扫描
			|-使用原则
					|-复合索引按f1,f2,f3次序建立,where语句中若无f2= '1',会因f2不是索引第一个字段而无法进行索引查询
					|-索引查询避免任何形式计算,并将操作移到等号右边
					|-如下操作会显式阻止Oracle使用索引:is(not) null, not in, !=, like, numeric_col+ 0, date_col+ 0; char_col||'', to_char, to_number, to_date;
			|-创建索引
					|-CREATE INDEX student_index ON student(sid, sname);
					|-注:建立索引时,组合的顺序关系非常重要
			|-索引存储
					|-索引和表独立存在,建议两种不要放置于同一表空间,从而避免IO冲突。
			|-删除索引
					|-DROP INDEX student_index ;
			|-管理索引
					|-先插入数据后再创建索引
					|-为索引指定表空间		
			
			
	|-SQL优化
			|-实质
					|-在结果正确的前提下,
							用优化器可识别的语句,
							充分利用索引,
							执行过程中访问尽量少的数据块,减少表扫描的I/O次数,
							尽量避免全表扫描和其它额外开销。
			|-优化器
					|-RBO- rule-based-opimizer
							|-根据自己内部设定的规则进行
					|-CBO- cost-based-opimizer
							|-建议使用,更多地根据表及索引的状态信息来选择计划
			|-尽量少用IN,而用EXISTS代替
					|-主大子小用IN,主小子大用EXISTS
			|-用NOT EXISTS或外连接代替NOT IN
					|-因为NOT IN不能应用表的索引
			|-尽量不用<> 或者!= 操作符
					|-不等于操作符永远不会用到索引,对它的处理只会产生全表扫描
			|-设计表的时候,将索引列设置为NOT NULL
					|-判断字段是否为空是不会应用到索引的,因为B树索引是不索引空值的
			|-尽量不用能配符"%"或 "_"做为查询字符串的第一个字符
					|-出现如上的情况时,索引是不会被使用的
			|-WHERE子句中避免在索引列上使用计算
					|-如果索引并非基于函数的,那么当在Where子句中对索引列使用函数时,索引不再志作用
			|-用">="替代">"
					|-A>2时,ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找=3的记录索引
			|-利用SGA共享池,避开parse阶段
					|-不同区域出现的相同SQL语句要保证查询字符完全相同,建议经常使用的用常量代替,以利用SGA共享池,避开parse阶段,防止相同的sql语句被多次分析
					|-其中存储过程就是提高效率的一种有效方法
			|-WHERE后面的条件顺序要求
					|-表连接语句写在最前面,可以过滤掉最大数量记录的条件居后
			|-使用表的别名,并将之作为每列的前缀
					|-连接多表时,使用表别名并作为列前缀,可以减少解析时间
			|-进行显式或隐式运算的字段不能进行索引
					|-所以与索引列进行比较的时候,只进行结果比较,不对索引列进行数值计算
			|-用UNION ALL代替UNION
					|-UNION会进行SORT UNIQUE,即数据唯一性校验,但实质连接的一般不会出现重复记录,所以可以采用UNION ALL,不排除重复记录行,效率可以更高
			|-改变ORACLE的SGA的大小
					|-定义
							|-数据库的系统全局区
					|-组成
							|-共享池+ 数据缓冲区+ 日志缓冲区
					|-共享池
							|-共享SQL区
									|-专门存放用户SQL命令,使用最近最少使用等优先级算法来更新覆盖
							|-数据字典缓冲区
									|-存放数据库的动态信息
									|-DBA可查看这些内存的命中率以从数据库的角度对数据库性能调优
											|-查看共享区SQL的重用率:SELECT (SUM(pins- reloads))/ SUM(pins) AS "Lib Cache" FROM v$librarycache;
													|-低于90%时建议增加共享池大小
											|-查询数据字典缓冲区的命中率:SELECT (SUM(gets- getmisses- USAGE- fixed)/ SUM(gets)) AS "Row Cache" FROM v$rowcache;
													|-同样最好在90%以上,否则建议增加共享池大小
					|-数据缓冲区
							|-存放SQL运行结果到抓取到data block
									|-查看数据库缓冲区的使用情况SELECT NAME, VALUE FROM v$sysstat WHERE NAME IN('db block gets', 'consistent gets', 'physical reads');
											|-查看数据缓冲区的命中率:SELECT 1- (SUM(CASE WHEN NAME= 'physical reads' THEN VALUE ELSE 0 END) /(SUM(CASE WHEN NAME= 'consistent gets' THEN VALUE ELSE 0 END)+ SUM(CASE WHEN NAME= 'db block gets' THEN VALUE ELSE 0 END)))  FROM v$sysstat
													|-最好在90%以上,否则建议增加数据缓冲区大小
					|-日志缓冲区
							|-存放数据库生成的日志
									|-查看日志缓冲区的使用情况:SELECT NAME, VALUE FROM v$sysstat WHERE NAME IN ('redo entries', 'redo log space requests');
											|-计算日志缓冲区的申请失败率:SELECT SUM(CASE WHEN NAME= 'redo log space requests' THEN VALUE ELSE 0 END)/ SUM(CASE WHEN NAME= 'redo entries' THEN VALUE ELSE 0 END) FROM v$sysstat;
													|-失败率应接近0,否则说明日志缓冲区太小,需要增加。
			
			
	|-序列、同义词
			|-序列
					|-创建序列
							|-CREATE SEQUENCE temp_sq
								START WITH 1
								INCREMENT BY 1
								ORDER 
								CACHE 20 --可以关闭NOCACHE,但进行内存缓冲对性能有所提高
								NOCYCLE; --确保该序列用于多表的情况下,ID是唯一的	--CYCLE MAXVALUE 10,即到10后重新从1开始
					|-读取数值
							|-SELECT temp_sq.nextval FROM dual;
								SELECT temp_sq.currval FROM dual;	--必须调用nextval后才能使用currval
					|-改变增量
							|-注:不能改变当前值,只能改变增量:ALTER SEQUENCE temp_sq INCREMENT BY 3;
						|-实现表ID自增
								|-CREATE SEQUENCE temp_sq
									START WITH 1
									INCREMENT BY 1
									CACHE 20
									NOCYCLE;
									
									CREATE OR REPLACE TRIGGER trg_temp_insert
									BEFORE INSERT
									ON temp
									FOR EACH ROW
									BEGIN
									    SELECT temp_sq.nextval INTO :new.tmp_id FROM dual;
									END;
			|-同义词
					|-概念
							|-方便操作不同用户下的对象
							|-使两个应用程序使用不同的名字指向同一张表
							|-使不同用户指向同一张表
					|-创建同义词
							|-CREATE PUBLIC SYNONYM student FOR sys.student;
					|-删除同义词
							|-DROP PUBLIC SYNONYM student;
							
							
							
	|-PL SQL
			|-PL/SQL块
					|-DECLARE
						    eNO student.sid%TYPE;   --指定表中对应列类型
						    stu student%ROWTYPE;    --表结构的复合类型
						    eName VARCHAR2(30);     --此处只是展示使用方法,并无实际用途
						BEGIN
						    eNO:= &请输入学号信息;         --进行数据录入,其中&后面为界面显示名称
						    SELECT * INTO stu FROM  student WHERE sid= eNO;
						    DBMS_OUTPUT.put_line('编号为'||eNO||'雇员的姓名为:'||stu.sname); --使用方法与表一致
						EXCEPTION
						    WHEN no_data_found THEN
						         DBMS_OUTPUT.put_line('没有此雇员信息');	--对应情况下的信息显示
						    WHEN ZERO_DIVIDE THEN
						         DBMS_OUTPUT.put_line('error');
						END;
			|-LOOP
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;  --给定初始值
						    LOOP
						        DBMS_OUTPUT.put_line(i);  --循环执行语句
						        EXIT WHEN i>= 10;
						        i:= i+ 1; --条件变更语句
						    END LOOP;
						END;
			|-WHILE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;  --给定初始值
						    WHILE(i<= 10) LOOP
						        DBMS_OUTPUT.put_line(i);
						        i:= i+ 1;
						    END LOOP;
						END;
			|-FOR
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    FOR i IN 1..10 LOOP
						        DBMS_OUTPUT.put_line(i);
						    END LOOP;
						END;
			|-IF
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    END IF;
						END;
			|-IF ESLE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    ELSE
						       DBMS_OUTPUT.put_line(i||'>= 10');
						    END IF;
						END;
			|-IF ESLIF ELSE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    ELSIF i> 20 THEN
						       DBMS_OUTPUT.put_line(i||'> 20');
						    ELSE
						       DBMS_OUTPUT.put_line('10< '||i||'< 20');
						    END IF;
						END;
			|-GOTO
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       GOTO to1;
						    ELSIF i> 20 THEN
						       GOTO to2;
						    ELSE
						       GOTO to3;
						    END IF;
						    <<to1>>
						        DBMS_OUTPUT.put_line(i||'< 10');
						    <<to2>>
						        DBMS_OUTPUT.put_line(i||'> 20');
						    <<to3>>
						        DBMS_OUTPUT.put_line('10< '||i||'< 20');
						END;
			
			
	|-游标、函数
			|-游标
					|-实质
							|-PL/SQL控制结构,便于对表的行数据逐条进行处理,但它并非数据库对象,只存留在内存中
					|-操作步骤
							|-声明游标
							|-打开游标
							|-取出结果,注结果取出的为一行数据
							|-关闭游标
					|-例子
							|-FOR循环操作游标,游标只作为结果集
									|-DECLARE
										CURSOR tmpCur IS SELECT * FROM student WHERE ssex= '男';
										stu student%ROWTYPE;
										sID NUMBER;
										BEGIN
										FOR stu IN tmpCur LOOP
										    sID:= tmpCur%ROWCOUNT;
										    DBMS_OUTPUT.put_line(sID||'ID= '||stu.sID||' ,sName= '||stu.sName);
										END LOOP;
										END;
							|-遍历游标,进行数据处理
									|-DECLARE
										CURSOR tmpCur IS SELECT * FROM student WHERE ssex= '男';  --进行游标声明
										stu student%ROWTYPE;
										sID NUMBER;
										BEGIN
										    IF tmpCur%ISOPEN THEN --打开游标前先进行确认游标是否已经打开
										       NULL;
										    ELSE
										       OPEN tmpCur;
										    END IF;
										    
										    FETCH tmpCur INTO stu;     --游标数据封装至变量中
										    WHILE(tmpCur%FOUND) LOOP   --判断该行是否有数据
										        DBMS_OUTPUT.put_line('ID= '||stu.sID||' ,sName= '||stu.sName);
										        FETCH tmpCur INTO stu;
										    END LOOP;
										END;
			|-函数
					|-创建
							|-CREATE OR REPLACE FUNCTION test(sIn student.sID%TYPE)
								RETURN  student.sName%TYPE
								AS
								    sOut student.sName%TYPE;
								BEGIN
								    SELECT s.sname INTO sOut FROM student s WHERE s.sID= sIn;
								    RETURN sOut;
								END;
					|-使用
							|-SELECT test(80308078) FROM dual;




	|-存储过程
			|-创建存储过程
					|-CREATE OR REPLACE PROCEDURE pro(
				       sNO IN student.sid%TYPE, --IN表示只录入
				       sXM OUT student.sname%TYPE --OUT表示只作为数据输出之用
						)
						AS
						BEGIN
						    SELECT sName INTO sXM FROM student WHERE sid= sNO;
						END;
			|-执行
					|-DECLARE
						  sXM student.sName%TYPE;
						BEGIN
						  pro(80308078, sXM);
						  DBMS_OUTPUT.put_line(sXM);
						END;
			|-删除存储过程
					|-DROP PROCEDURE pro;




	|-触发器
			|-实质
					|-存放数据库,并被隐含执行的存储过程。
			|-创建(语句& 行触发器)
					|-CREATE OR REPLACE TRIGGER tr_student_dml
						BEFORE INSERT OR UPDATE OR DELETE
						ON student
						BEGIN IF to_char(SYSDATE, 'dy') IN ('星期六', '星期天') THEN
						    CASE
						        WHEN inserting THEN
						            raise_application_error(-20001, '对不起,不能在指定日期插入档案信息'); --用于返回自定义错误信息,数值支持-20000~-20999
						        WHEN updating THEN
						            raise_application_error(-20001, '对不起,不能在指定日期更新档案信息');
						        WHEN deleting THEN
						            raise_application_error(-20001, '对不起,不能在指定日期删除档案信息');
						    END CASE;
						END IF;
						END;
						
						--建立关于student表的增、删、改次记录
						CREATE TABLE count_table(
						    cName VARCHAR2(30) NOT NULL,
						    bAdd NUMBER(1) DEFAULT 0,
						    bDelete NUMBER(1) DEFAULT 0,
						    bUpdate NUMBER(1) DEFAULT 0,
						    dChangeDate DATE  DEFAULT SYSDATE
						);


						CREATE OR REPLACE TRIGGER tr_count_student
						AFTER INSERT OR UPDATE OR DELETE
						ON student
						FOR EACH ROW --针对一语句影响多条的情况,针对每条进行处理	--行触发,不加则行语句触发
						BEGIN    --基于对student表的触发,则代码不能从触发器所对应的基表中读取数据
						    CASE 
						        WHEN inserting THEN
						            INSERT INTO count_table VALUES(upper('student'), 1, 0, 0, SYSDATE);
						            DBMS_OUTPUT.PUT_LINE(:new.sName);    --:new表示当前记录,:old表示还旧记录
						        WHEN updating THEN
						            INSERT INTO count_table VALUES(upper('student'), 0, 1, 0, SYSDATE);
						        WHEN deleting THEN
						            INSERT INTO count_table VALUES(upper('student'), 0, 0, 1, SYSDATE);
						    END CASE;
						END;
			|-测试
					|-DECLARE
						    no_babies_allowed EXCEPTION;
						    PRAGMA EXCEPTION_INIT(no_babies_allowed, -20001);     --预编译将名称与用于触发器中的错误号码关联起来
						BEGIN
						    INSERT INTO student VALUES (1, 'yao', '男', 1, '');
						EXCEPTION
						    WHEN no_babies_allowed THEN    --SQLERRM 将传递给内置过程 RAISE_APPLICATION_ERROR 的消息返回
						        DBMS_OUTPUT.PUT_LINE(SQLERRM);       --返回指定代码错误
						END;
			|-作用
					|-控制数据安全:在非工作时间不能对表进行操作
					|-实现数据统计
					|-实现数据的完整性,进行数据的限制
					|-实现参照完整性:比如级联更新
			|-系统事件触发器
					|-基于Oracle系统事件(LOGON/STARTUP)所建立的触发器,提供跟踪系统或数据库变化的机制。
					|-常用事件属性函数
							|-ora_client_ip_address:返回客户端IP地址
							|-ora_database_name:返回当前数据库名
							|-ora_des_encrypted_password:返回DEX加密后的用户口令
							|-ora_dict_obj_name:返回DDL操作中所对应的数据库对象名
							|-ora_dict_obj_name_list(name_list OUT, ora_name_list_t):事件中被修改的对象名列表
							|-ora_dict_obj_type:返回DDL操作所对应的数据库对象类型
							|-ora_grantee(user_list OUT ora_name_list_t):返回授权事件的授权者
							|-ora_instance_num:返回例程号
							|-ora_is_alter_column(column_name IN VARCHAR2):检测特定列是否被修改
							|-ora_is_creating_nested_table:检测是否正在建立嵌套表
							|-ora_is_drop_column(column_name IN VARCHAR2):检测特定列是否被删除
							|-ora_is_servererror(error_number):检测是否返回特定Oracle错误
							|-ora_login_user:登陆用户名
							|-ora_sysevent:返回触发触发器的系统事件名
					|-常用系统触发
							|-开户关闭数据库时进行记录
										CREATE TABLE sysevent_recored(
										    event VARCHAR2(100),
										    TIME DATE
										);
		
										CREATE OR REPLACE TRIGGER tr_startup
										AFTER startup
										ON DATABASE
										BEGIN
										    INSERT INTO sysevent_recored VALUES(ora_sysevent, SYSDATE);
										END;
										CREATE OR REPLACE TRIGGER tr_shutdown
										BEFORE SHUTDOWN
										ON DATABASE
										BEGIN
										    INSERT INTO sysevent_recored VALUES(ora_sysevent, SYSDATE);
										END;
							|-进行用户登陆退出触发
										CREATE TABLE log_record(
										    username VARCHAR2(30),
										    logon_time DATE,
										    logoff_time DATE,
										    address VARCHAR2(100)
										);
										
										CREATE OR REPLACE TRIGGER tr_logon
										AFTER logon
										ON DATABASE
										BEGIN
										    INSERT INTO log_record VALUES(username, logon_time, address) VALUES( ora_login_user, SYSDATE, ora_client_ip_address);
										END;
										CREATE OR REPLACE TRIGGER tr_logoff
										BEFORE logoff
										ON DATABASE
										BEGIN
										    INSERT INTO log_record VALUES(username, logoff_time, address) VALUES( ora_login_user, SYSDATE, ora_client_ip_address);
										END;
					|-触发器管理
							|-显示触发器信息
									|-SELECT status, ut.* FROM User_Triggers ut;
							|-禁止
									|-ALTER TRIGGER TR_LOGOFF DISABLE;
									|-针对某表的所有触发器生效:ALTER TABLE student DISABLE ALL TRIGGERS;
							|-激活
									|-ALTER TRIGGER TR_LOGOFF ENABLE;
									|-ALTER TABLE student ENABLE ALL TRIGGERS;
							|-重新编译
									|-针对表结构发生变化后,触发器进行INVALID状态,需重新编译进行触发:ALTER TRIGGER TR_STUDENT_DML COMPILE;
							|-删除
									|-DROP TRIGGER TR_STUDENT_DML;






	|-事务控制
			|-实质
					|-在Oracle的每个连接中都会产生一个Session,一个Session对数据库的修改,不会立刻反应到数据库的真实数据上,是允许回滚的。只有当提交了,才会变成持久数据。
			|-原子性
					|-一个事务中,包含的若干个操作是一个整体需一起完成实现。
			|-一致性
					|-事务未提交前,修改用户和其它用户所见一致,其中其它用户所见一致。
			|-隔离性
					|-未完成的事务不可见
			|-持久性
					|-事务提交后数据更新为持久数据






	|-用户管理
			|-创建用户
					|-CREATE USER test IDENTIFIED BY test;
			|-删除用户
					|-
			|-创建Session权限
					|-分配连接权限,但还不能进行任何操作:GRANT CREATE SESSION TO test;
			|-用户角色
					|-GRANT 
							CONNECT, --连接
					      	RESOURCE, --基本的业务表等的创建
					      	UNLIMITED TABLESPACE, --表空间操作
					     	 --DBA, --所有数据库权限集合,不建议
					      	SELECT_CATALOG_ROLE,  --查询数据字典视图和包
					     	 EXP_FULL_DATABASE,
					      	IMP_FULL_DATABASE     --数据导入导出工具的使用
						TO test;
			|-锁定用户
					|-ALTER USER test ACCOUNT LOCK   --UNLOCK
			|-密码失效
					|-密码失效,会提示输入新密码:ALTER USER test PASSWORD EXPIRE;
			|-对象授权
					|-GRANT SELECT ON yqj.student TO test;
					|-GRANT ALL ON yqj.student TO test; --提供表的所有权限
					|-GRANT UPDATE(sid) ON yqj.student TO test; --控制到列权限
			|-权限回收
					|-注意只能回收表层次的权限,如对列的控制无法回收:REVOKE ALL ON yqj.student FROM test;
			|-查看权限
					|-查看当前用户权限信息:SELECT * FROM user_sys_privs;
			|-权限传递
					|-权限sys->test->next,而移除test权限后,不影响next的权限:GRANT CREATE SESSION TO test WITH ADMIN OPTION;
			|-角色
					|-CREATE ROLE testRole;
					|-GRANT CREATE TABLE TO testRole;
					|-DROP ROLE testRole;
			|-完整流程
					|-
							--创建表空间
							CREATE TABLESPACE test
							DATAFILE 'D:\oracle\product\10.2.0\oradata\orcl\test.ora'
							SIZE 200M
							AUTOEXTEND ON NEXT 50M
							EXTENT MANAGEMENT LOCAL
							SEGMENT SPACE MANAGEMENT AUTO;
							
							CREATE TEMPORARY TABLESPACE test_temp
							TEMPFILE 'D:\oracle\product\10.2.0\oradata\orcl\test_temp.dbf'
							SIZE 50M
							AUTOEXTEND ON NEXT 50M
							EXTENT MANAGEMENT LOCAL;
							
							--增加相关用户及权限
							CREATE USER test IDENTIFIED BY test
							DEFAULT TABLESPACE test
							TEMPORARY TABLESPACE test_temp;
							
							--增加相关用户权限
							GRANT ALL PRIVILEGES TO test;
							
							--测试连接
							SELECT * FROM user_sys_privs;
			
			
			
			|-备份 恢复 SQLLDR
					|-IMP/EXP
							|-
								--完全导出/导入,导出整个数据库
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE= D:\FULL.DMP FULL= Y;
								--导出/导入指定用户信息
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE= D:\YQJ.DMP OWNER= YQJ;
								--导出/导入指定用户信息下的指定表
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE=D:\YQJ_STUDENT.DMP TABLES=(STUDENT); --OWNER=orcl 
					|-SQLLDR
							|-整理数据至CSV
									|-   	NAME	AGE	ADDRESS		CARDNO
												1			23	福建省			350582198903164000
												2			24	福建省			350582198903164001
												3			25	福建省			350582198903164002
												4			26	福建省			350582198903164003
							|-创建对应表
									|-CREATE TABLE sqlloader(
										NAME VARCHAR2(100) NOT NULL,
										age NUMBER(3) CHECK(age<300 AND age> 18),
										address VARCHAR2(300),
										cardNo VARCHAR2(50) UNIQUE NOT NULL
										);
							|-创建控制文件sqlloader.ctl
									|-load DATA           --控制文件标识
										infile 'd:\sqlloader.csv'   --输入的数据文件名
										append INTO TABLE sqlloader    --向表追加记录
										       --insert为缺省方式,要求表为空
										       --replace/truncate,删除旧记录并替换
										fields terminated BY ","
										optionally enclosed BY '"'
										(NAME, age, address, cardNo)--对应表单的字段名称
							|-CMD执行调用语句
									|-sqlldr userid=yqj/yqj control= d:\sqlloader.ctl




	|-数据库设计范式
			|-字段设计为不可再分
			|-两张表的关系,在第三张表中体现
			|-多张表中,只存关系,不存具体信息
			|-表关联越少越好,SQL语句复杂度越低越好
			
			
			
			
			
	|-Oracle跨库查询
		|-建立DBlink 
			|-情况一:
					|-本地tnsnames.ora已配置如下
						|-bylw =
						  (DESCRIPTION =
						  (ADDRESS_LIST =
						  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))
						  )
						  (CONNECT_DATA =
						  (SERVER = DEDICATED)
						  (SERVICE_NAME = bylw)
						  )
						  )
					|-登陆创建链接
						|-create public database link
  						to_bylw connect to scott identified by tiger using 'bylw';
			|-情况二:
					|-本地tnsnames.ora中未配置
							|-	create database link to_test
							  connect to scott identified by tiger
							  using '(DESCRIPTION =
							  (ADDRESS_LIST =
							  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))
							  )
							  (CONNECT_DATA =
							  (SERVER = DEDICATED)
							  (SERVICE_NAME = bylw)
							  )
							  )';
							
		|-使用方式如下
			|-select * from scott.tb_test@to_bylw;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章