zoukankan      html  css  js  c++  java
  • Oracle数据库 2021.1.7~2021.1.13

    六天心得

    Oracle学了6天,学的挺快的,老师只根据我们的情况与需求讲了部分吧,感觉没有前面学java学的扎实,每天都是只学习理论知识,并没有做过什么练习和作业;话说oracle也并没有想象中这么难,只是多了很多它自己的东西,pl-sql;

    ORACLE

    网络资料:https://docs.oracle.com/cd/E11882_01/index.htm(oracle数据库文档11.2)

    https://bk.tw.lvfukeji.com/baike-数据库规范化?wprov=srpw1_3(数据库规范化)

    dba/dbo:数据库管理员/操作员

    db:数据库

    dbms:数据库管理系统

    rdbms:关系型数据库管理系统-->oracle

    SQL

    structure query languge 结构化查询语言(设计之初是为了应用于关系型数据库,数据库都要遵循这个标准,数据库sql之间有着细小的区别)

    rdb:关系型数据库-->为了解决数据关联性的问题;

    数据类型(DataType)

    (oracle能够识别任意一种数据库类型)

    Character Data Types(字符数据类型)

    存储字符数据,任意数据文本

    CHAR Data Type:固定长度的字符串,最大为2000字节,当数据类型要求固定时可以使用,比如性别等。(NCHAR Data Type-->N-->字符编码采用Unicode的)

    ​ char(length)可以存储length个byte的字符串;

    ​ char(length char)可以存储length个插入的字符;

    ​ 如果插入的值小于char的长度,oracle将会在值的右边补空格直到指定的长度为止;

    ​ 如果插入的值大于char的长度,oracle将会报错。

    VARCHAR2 Data Type:可变长度的字符串,精准插入字符,插入几个保存几个字节/字符,比CHAR更节省内存,最大为4000字节。(VARCHAR Data Type-->VARCHAR2 Data Type是升级版,NVARCHAR2 Data Type-->N-->字符编码采用Unicode的)

    ​ varchar2(length)

    ​ varchar2(length char)

    length为插入的最大长度,最小为一个字节,但是传入的值可以为空,不能超过指定的插入的长度,不然会报错;实际存储的值与插入指定的值是一致的。

    Numeric Data Types(数字数据类型)

    可以存储正数、负数、浮点数、零、无穷数、"not a number"非数字-->NAN。

    NUMBER Data Type:正数,负数,零,固定的数。范围:1.0 x 10^-130到1.0 x 10^126不包含本身。

    ​ NUMBER(p,s):

    ​ NUMBER(p)

    ​ p:precision(精确度),数字所有有效的部分

    ​ s:scale(扩展),扩展的部分,小数点后面的。

    ​ p与s的位数时共用的,输入的值整数部分加小数部分必须小于等于p,不然会报错;当s小于输入值的小数部分,则可以四舍五入,能够截取,(例如:123.89-->NUMBER(6,1)-->123.9)整数不能;负数是从整数位往前推几位,后面都为0(例如:123.89-->NUMBER(6,-2)-->100.00),范围:-84到127;

    FOLAT Data Type(BINARY_FLOAT32位,BINARY_DOUBLE64位,二进制的)

    ​ FOLAT(n);

    ​ n:有效位;

    DATE Data Type:日期加时间(已经够用)

    ​ datetime

    ​ 格式:to_date('timevalue','YYYY-MM-DD HH24:MI:SS')

    TIMSTAMP Data Type:对DATE的扩展,还带地理位置,有时区;

    LARGE OBJECT:

    插入图片,文档等;

    运算符(这里的是各个数据库通用的)

    比较运算符

    (>,>=,<,<=,=,<>,!=);(<>与!=含义一致)

    in,not in:范围内,不在范围内;(当需要多个字段在一个范围,where (column1,column2......)in.....)

    is null, is no null:为空,不为空;

    between x and y:在x到y范围之内,是闭区间;

    exists:某个值是否存在,较为复杂,空也是存在的,因为它为一行;

    like:模糊查找,主要查找字符串,通配符:"%" -->匹配任意长度的任意字符串和"_"-->单个任意字符,比较耗时,而且会让索引失效,并不是很好,数据量不能太大,小范围使用,初期能用用;

    逻辑运算符

    and or not:与,或,非;

    括号运算符

    () 改变运算优先级

    数据库设计三范式(数据库统一的标准)

    尽量去满足这个三个规范,一般2NF都有,1NF与3NF不一定满足。

    1NF:列不可分,为了排除重复组的出现,所采用的方法是要求数据库的每个列的值域都是由原子值(不可分)组成;每个字段的值都只能是单一的值。

    2NF:数据表中除了主键之外的其他列,都必须依赖于主键存在,不然不应该设计在同一表中。(主键-->自增int数字,为了方便区分,比较,数字之间比较很快,方便索引存储)

    3NF:要求所有非主键属性都只和候选键有相关性,也就是说非主键属性直接应该是独立无关的。

    sql语句

    1、DDL,数据定义语言,建,修改,删除表等的语句
    create table 建表(desc tableName 查看表信息)
    create table tableName(column definition references FK_tableName(id),(在创建时添加外键)column definition )(column字段/列,definiton定义)
    column definition(字段的定义):
    columnName(字段名),datatype(数据类型), constraint(约束)。
    constraint (约束): not null(非空),primary key(主键),foregin key(外键),(默认值)default value...
    

    建立表的结构时,存储数据之前,要先把数据的格式给定义清楚。命名根据公司的规范,没有就尽量符合java的命名规范就行。

    alter table 修改表
    	add column(添加列)
    		alter table tableName add column defintion;
    	drop column(删除列)
    		alter table tableName drop column columnName;
    	modify column datatype(修改列的数据类型)(必须先保证列的值为空)
    		alter table tableName modify columnName newDatatype;
    	rename column name(修改列的名称)
    		alter table tableName rename column oldColumName to newColumName;
    	rename table(修改表的名称)
    		alter table tableName rename to newTableName;
    
    constraint 约束

    ​ 非空约束:

    ​ 主键约束:(非空约束+唯一约束)

    	alter table tableName add constraint PK_NAEM primary key(columnName);(添加主键约束,括号里可以填两列,称为联合主键约束,但一般很难见到)
    
    	alter table tableName drop constranint PK_NAEM;(删除主键约束)
    

    ​ 唯一约束:(空值不会受限制)

    	alter table tableName add constraint UQ_NAME urique(columName);(添加)
    	alter table tableName drop constraint UQ_NAME;(删除)
    

    ​ 外键约束:

    ​ 含义:表与表之间数据的关系,另外一张表的主键放在另一张表中作为一个字段来联系两张表。

    	alter table tableName add constraint FK_NAEM foreign key(NewcolumName) references PK_TABLE_NAEM(PK_COLUMN_NAME);(这里的新的字段名必须先存在)
    

    ​ 主键表(主表),外键表(从表),删除数据时需要先删除从表的,才能再删主表的。

    ​ 检查约束:(mysql不支持)

    	alter table tableName add constraint CK_NAME check(check expression);(添加)
    	alter table tableName drop constraint CK_NAME;(删除)
    
    drop table删除表
    drop table tableName;
    
    2、DML,对数据表进行操作的语句

    插入,修改,删除-->更新语句;查询-->查询语句。

    INSERT 插入数据。
    insert into tableName(columnName,columnName,...) value(columNameValue,...);--字符串需要使用单引号,前后括号的值需要对应,顺序,个数。
    
    UPDATE 修改数据
    update tableName set colunmName =somevalue,colunmName =somevalue...... where condition;
    --(可以改多个属性,也可以根据条件改几行)
    
    DELETE 删除数据
    delete from tableName where condition;
    
    SELECT 查询语句(最复杂,单独为一类)
    query(标准的查询语句)

    (执行顺序,from-->where-->group by-->having-->order by-->)

    ​ selcet:(选择列)column 别名(前面不能加as,mysql可以;当别名为字符串时不加单引号,某些数据库要加,别名可指代这个字段)不能加*来查询全部,因为在数据大时与填写字段查会有很大区别,数据库优化第一步,去除所有 的 *,

    ​ from tableName(来源那张表)

    ​ where 对记录进行筛选

    聚合函数/单行函数:max最大值,min最小值;(对字符串进行比较时,看编码集大小)sum(求和,只能对数字使用),avg(平均值),count(1-->id主键,统计表的所有字段,统计);(聚合函数调用时,所有null值都会被忽略;数据库通用的函数)

    ​ nvl(columnName,defaultvalue):并不是数据库通用的,部分数据库有,设置默认值,当字段值为空时,会自动填充默认值。(oracle中十分重要)

    ​ group by colum:分组,将值相同的分到同一组;一般都会与聚合函数联用,为了方便展示,因为分组后会根据字段值分为几个组的数据,数据条数可能不同,不好展示。having:对group by的结果进行再次过滤,针对分组后的几个组的数据进行过滤,不需要对那个字段进行过滤;后面也加聚合函数,与group by使用的聚合函数可以相同也可以不同;

    ​ order by column;根据字段排序,可通过多个字段排序,默认升序asc,降序desc;(空值排序没有统一标准)

    多表查询(左连接,右连接,全连接,内连接,笛卡尔集)

    ​ 以空间换取时间

    (权限设计,五表权限-->user用户 user_role role角色 role_resource resource权限)

    ​ 左/右连接:拿左/右边的表为基准,根据某一个字段拼接右/左边这张表,一般要以多,外键表来作为基准,这样就不会重复数据,根据具体情况而定;连接查询后,表的字段会横向变多,

    ​ form tableName1 left/right join tableName2 on(table1.column = tableName2.column );

    ​ 内连接:inner join,取交集,以全连接作为基准,筛选条件符合的数据;

    ​ 全连接:full join,左连接+右连接;

    ​ 笛卡尔集:拿a表的每一条去拼接b表的每一条,a*b;

    select column from tableName1,tableName2; 
    
    select * from tableName1,tableName2 where table1.column = tableName2.column;--与内连接效果相同
    
    子查询,条件子查询

    ​ 条件子查询:将一个查询作为另一个查询的条件;

    ​ 例子,查询每个部门中薪水最大的人的信息

    select deptid,max(salary) from emp group by deptid;这条语句查询了每个部门id和最大薪水,而查询的人必须再从emp中筛选,且满足上面的部门id与薪水。可以把这个查询的数据作为一张临时表,再用emp表去内连接它:

    select emp.* from emp,(
    
    select deptid,max(salary) maxsalary from emp group by deptid
    
    ) emp2 where emp.deptid=emp2.deptid and emp.salary=emp2.maxsalary;
    
    --另一种实现方法:
    
    select * from emp e where e.salary =(
    
    select max(salary) from emp e2 where e.deptid = e2.deptid group by e.deptid
    
    );--可看作关联子查询,条件子查询,这条性能没有上面的好,要进行多次筛选。	
    
    	select distinst column from tableName;--去重,但公司禁用,性能太低,数据量大时运行容易出问题。
    
    	--查找重复的数据
    	
    	select * from table where column in(
            
    	select column from tableName group by column having count(1)>1);
    
    	--删除重复的数据
    	
    	delete from tableName where name in
    	
    	(select name from tableName group by name having count(1)>1)
    	
    	and id not in
    	
    	(select max(id) from tableName group by name having count(1)>1);--删除name重复项且留下id最大的name;
    
    横竖表转换

    ​ 横表在操作时,需要跨很多表进行操作,这明显不现实,并且设计时将会有很多张表;而竖表会更加方便,操作更加方便,但数据量会变大,以空间换时间;所以我们会设计使用竖表,展示使用横表展示给用户。

    横表

    id name shuxue yuwen yinyu
    1 xxx 90 80 70
    2 xxx2 80 90 70

    竖表

    id name subject chengji
    1 xxx 数学 90
    2 xxx 语文 80
    3 xxx 英语 60

    横表转竖表

    insert into score2--(直接将表插入)
    
    select name,'语文' subject,yuwen from score1;
    
    union--(纵向地拼接结果集)
    
    select name,'数学',shuxue,from score1;
    
    union
    
    select name,'英语',yingyu,from score1;
    

    竖表转横表

    select t1.name,t1.score yuwen,t2.score shuxue,t3.score yingyu from(  
    select name,score from score2 where subject =‘语文’; 
    )t1
    
    left join
    
    (  
    select name,score from score2 where subject =‘数学’;
    )t2 on t1.name = t2.name
    
    left join
    
    (   
    select name,score from score2 where subject =‘英语’;   
    )t3 on t2.name = t3.name
    
    结果集运算
    	minus -减 union +加 (plus)INTERSECT 求交集
    
    	union [all](并集,默认会去重,加上all不去重)
    	select column1,column2 from tableName
    	union
    	select column3,column4 from tableName;(纵向拼接/相加两个表,上下两个对应的字段可以名字不同,但数量和数据类型必须相同)
    	minus(差集)
    
    select * from student where rownum<=4
    minus
    select * from student where rownum<=2;(这条用于学习minus集合相减,性能并不好)
    

    PLSQL编程

    ​ 基于sql语句,是oracle用来操作数据库的扩展,体现oracle的不同,提升其操作性能;P-->存储过程,L-->language;除了sql的数据类型,还会有扩展的数据类型,集合,记录等;

    静态sql语句,自己写定的;

    动态sql语句,由别人传过来的,事先不知道的;

    ​ EXECUTE IMMEDIATE 字符串:立即执行

    declare
    	mysql varchar2(50);
    begin
    	mysql:=&mysql;--会弹出一个输入框让你输入mysql的值,可以输入一条sql更新命令,命令需要用单引号引起
    	dbms_output.put_line(mysql);
    	execute immediate mysql;--执行这条sql语句,如果是查询语句不会有结果,因为是pl-sql语句块,不是正常的sql语句
    end
    
    select * from student;--查询更新结果
    

    1、基本组成

    declare -- 变量声明
    begin 
    		-- 业务逻辑
    exception -- 异常处理[可选]
    end;
    

    2、hello word(例子)

    begin
    	dbms_output.put_line('hello world');(打印语句不能打印布尔值)
    end;
    

    3、变量声明

    ​ declare

    ​ 变量名 CONSTANT(加上为声明常量) 变量的数据类型(可为sql datatype,也可为 pl/sql datatype) :=变量值;(:=赋值运算符)

    ​ begin

    ​ 变量名:=变量值;(也可分开写,先定义后赋值)

    ​ 业务逻辑

    ​ end;

    赋值运算符

    ​ :=,select into

    	declare
    	i int;
    	begin
    	select 123 into i;--(可以查出某个数据或者将某个数据赋给一个变量)
    	end
    

    4、运算符(与sql差不多)

    ​ 算术运算符

    ​ + - * / **(多少次幂)

    ​ ||:连接符,拼接两个字符串;

    ​ 2**3:2的3次方;

    ​ 比较运算符

    ​ 字符串比较用is;

    ​ 逻辑运算:and,or,not;(boolean值除了true,false外,还可以为null,如果不赋值的话,默认为空)

    ​ true and null ==> null;

    ​ true or null ==> true;

    ​ null and null ==> null;

    ​ 赋值运算符

    5、流程控制

    (1)顺序流程
    (2)分支/选择流程控制
    if、if else、if elsif语句
    		if condition then
    			statement;
    		end if;
    
    
    		if condition then
    			statement;
    		else
    			statement;
    		end if;
    
    
    		if condition then
    			statement;
    		elsif condition then
    			statement;
    		[elsif condition then......]
    		end if;
    
    case when
    		case var
    			when constant then statement;
    			[when constant then statement;......]
    			else statement;
    		end case;
    		secach case(多个条件分别进行判断)
    			case 
    			when condition then statement;
    			[when condition then statement;......]
    			else statement;
    		end case;
    
    (3)循环流程
    a、Basic LOOP

    ​ (exit-->相当于java中的back,exit when 当条件满足时结束循环,if condition exit end if <===> exit when condition;continue,continue when)

    loop
    statement;
    end loop;
    
    b、FOR LOOP Index

    for index in [reverse] (反向) lower_bound..upper_bound(范围,只能从小到大,包括两个边界值) loop(这里的index在循环体中只能读,不能修改,可赋值给别的变量;且与循环体外的同名的index不相关,出了循环体,index不能使用;如要在循环体内使用循环体外与index同名的变量,则需要使用main.index)
    statement;
    end loop;
    
    c、WHILE LOOP
    while condition loop
    statement;
    end loop;
    
    d、GOTO statement
    e、NULL statement

    ​ null;(什么都不执行)

    6、pl-sql DataType

    ​ a、boolean

    ​ b、integer

    ​ c、cursor

    ​ d、%type %rowtype

    ​ %type(变量2取前面变量1/字段一样的数据类型)

    ​ 变量2 变量1/字段名%type;

    ​ 多使用在查询某个字段,根据字段的类型给某个变量赋数据类型,以方便赋值;

    ​ 例子:

    		declare
    			maxage studnet.age%type;
    		begin
    			select max(age) into maxage from student;(查询兼赋值)
    		end; 
    

    ​ %rowtype (某一条记录的数据类型)

    ​ 变量名 tableName%rowtype;(存储一行的数据)

    ​ 例子:

    		declare
    			sturow student%rowtype;
    		begin
    			select * into sturow from student where id = 1;
    			dbms_output.put_line(sturow.name || '--' || sturow.age);
    		end;
    

    7、伪例

    ​ 在oracle执行查询语句时,所临时生成的字段(列);

    rownum 查询时生成的序号;(不适用于直接的>计算)

    ​ 用来做分页查询(淘宝使用的全文搜索 Elestatic Seach ES,该技术基于谷歌的论文, lucene谷歌的技术)

    例子1:

    select id,name,age,gender from
    (
    select rownum,tableName* from tableName where rownum<=2;
    )
    

    -- from student

    -- 提取第一条记录 rownum(1) 1 aaa 18 male

    -- 提取第二条记录 rownum(2) 2 abc 19 female

    例子2:

    select rownum,student.* from student where rownum <= 4 and rownum>2;
    

    -- from student

    -- 提取第一条记录 rownum(1) 1 aaa 18 male(不符合where条件,去掉,rownum会跟记录一起丢弃,所以后面两条将会是rownum(1),(2),所以四条记录都不符合条件,上面语句不会查出记录)

    -- 提取第二条记录 rownum(2) 2 abc 19 female (同理)

    下面是正确的解法:(与分页查询相关)

    ​ currentPage 当前第几页;

    ​ pageSize 每页显示多少条

    	select id,name,age,gender
    	from
    	(
    select rownum r,student.* from student where rownum<=4(currentPage * pageSize表示这页结束后的总记录条数)
    	) t where t.r>2((currentPage-1) * pageSize前面页数的记录总和); 
    
    rowid 查询时生成的唯一的字符串(oracle独有);

    ​ 特点:给了表的每一行记录后,值就不会变,无论怎么查询,不会像rownum一样根据查询的记录数发生改变;如果将某条记录删除后,再次插入一条新的,则rowid也会改变;

    8、cursor(游标,一种静态sql)

    ​ 含义:一个指针,指向一个私有的sql区域,关于一个select语句或者dml语句的执行过程中的信息;(与jdbc中的结果集类似)

    ​ 作用:

    implicit cursor/sql cursor:隐式游标,PL-SQL创建和管理的;

    ​ oracle隐式游标只有一个,名字为sql;每次执行一个select,DML语句,PL-SQL就会打开一个叫做SQL的隐式游标,语句结束时,这个游标会自动关闭,但是它还是会保持一个可用的状态,直到下一个select,DML语句运行,前面的值将会覆盖掉,所以,如果没有运行下一个语句,sql的信息就是最近运行的那一条语句的信息;因为游标是session级别的,所以不会有并发的问题,我们执行不能在一个时间同时执行多条sql,只能执行一条sql语句,所以sql的信息会是最近执行的那一条语句的;(这时候可以在覆盖,也就是下一条语句覆盖之前,需要获取的sql信息赋给本地变量以便使用)

    ​ 可以通过SQLattribute来获取隐式游标的属性信息;(这里需要注意%isopen属性一直是false状态,因为每次运行sql时,结束后都会关闭,所以它是在执行语句的同时打开的,当你看到语句的结果时,已经关闭了)

    ​ SQL游标大部分用于更新语句,查询语句一般用显式游标;

    SQL游标的属性值:

    ​ select insert/update/delete

    ​ %isopen false false

    ​ %found 查询有结果return true,否则false 有影响的行数,true,否则false

    ​ %notfound 跟%found相反 跟%found相反

    ​ %rowcount 查询的结果集的记录数 受影响的行数

    explicit cursor:显式游标,由操作者创建和管理;
    a、显式游标的定义:

    ​ cursor cursorName is query sql;

    b、打开游标:

    ​ open cursorName:

    ​ 打开游标会执行如下动作:

    ​ a、分配数据库资源;

    ​ b、执行查询,标记好对应的结果集,如果有带有for updata子句,锁定结果集的记录;

    ​ c、将游标指向结果集第一行记录的前面(字段行)

    c、关闭游标:

    ​ close cursorName:

    ​ 关闭已打开的游标,关闭之后可以再次打开,没有关闭不能再次打开;

    d、抓取数据:

    ​ fetch cursorName into var:

    ​ 每次抓取一条记录,每抓取一次记录,游标自动向下移动;

    e、显式游标的属性:

    ​ %found(没有抓取数据之前,返回null,这时这个属性是没有意义的)

    ​ 分别返下列三种情况:

    ​ null:在游标打开之后,在第一次抓取数据之前,return null;

    ​ true:最近的一次fetch操作,如果返回了一行,return true;

    ​ false:除以上两种情况外,retrun false;

    ​ %notfound

    ​ 跟%found是逻辑的相反值

    ​ 返回null,true,false;(true与false的情况跟%found相反)

    ​ %isopen

    ​ 返回boolean,检查游标是否打开;(在代码量大时,在每次打开或者关闭游标时都需要使用这个进行判断,为了避免报错)

    ​ %rowcount

    ​ 在打开后,第一次抓取数据之前,使用返回为零,判断总共有多少条记录被fetch;

    f、for loop cursor(类似增强for循环)

    ​ for item(游标中每个变量的值) in cursorName loop

    ​ end loop;

    ​ 例子:

    declare
     cursor mycur is select * from student;
     sturow student%rowtype;(%rowtype表示一行记录的变量)
    begin
     for sturow in mycur loop--当循环开始时,游标会自动打开,循环结束时会自动关闭
     	dbms_output.put_line('id:' || sturow.id);--在循环里可以直接使用,会自动抓取值
     end loop;
    end;
    
    例子:(将一张表的信息全复制到另一张表中)

    ​ 第一种做法:(需要知道其id,并且这个id还必须是int类型,根据id一个一个查,再一个一个放入另一张表,十分麻烦)

    	declare
    		sturow student%rowtype;
    	begin
    		for i in 1..4 loop
    			select * into sturow from student where id=i;
    insert into student2(id,name,age,gender) 	values(sturow.id,sturow.name,sturow.age,sturow.gender);								    		end loop;
    	end;
    
    create table studnt2 as select * from student where 1<>1;(将表结构给到另一张表,不给里面的值,不加where条件则结构与数据都给另一张表)
    

    ​ 第二种使用游标:

    	declare	
    		cursor mycur is selcet * from student;
    		sturow student%rowtype;
    	begin
    		open mycur;
    		loop
    			fetch mycur into sturow;
    			dbms_output.put_line  (sturow.name);
    			exit when mycur%notfound;(抓取不到数据时退出)
    		end loop;
    		close mycur;
    	end
    
    session cursor会话级别游标:登入客户端一直有效,直到登出客户端才会失效;
    PGA cursor:全局级别游标,可跨会话使用;

    ​ (请求级别:一般语句里面的变量,在语句结束后就没有效果了;)

    9、sequence(序列,oracle独有)

    与自增的id差不多

    创建完sequence,将会从属于整个数据库,可以多个表使用;可以用它自动生成唯一的一个整形数,或者一个主键值,当这个序列产生后会自动往上加,独立在事务回滚之外的,如果多个用户并发地使用同一个序列,对它进行增长,这时要求有一个间隙,可以使用缓存cache来解决这个问题;

    create sequence sequenceName start with(从几开始) 
    integer increment by(自增的度长,默认每次加一,设置为几,每次加几)integer max/minvalue[no max/minvalue](最大/小值,没有最大/小值,一般设为九个九) 
    cycle[no cycle](循环,没有循环;意思是当到达设置的最大或最小值之后,再增则会回到开始值重新自增) 
    no/cache(缓存,先准备一个值放着,来的时候直接取值)
    no/order(不按顺序性能好一点,只要唯一就可以;按顺序);(这个自增值可以为负数,为负数,则可设置最小值;设置正数,则可设置最大值)
    

    例子:

    create sequence mysql start with 1 increment by 2 maxvalue 999999999;
    

    nextval currval(下一个,当前值)

    ​ nextval优先级大于currval,一行中多条nextval,只会执行一次nextval;

    ​ dual:虚拟表,虚拟表中永远都只有一条记录;(只计算一次表达式时使用)

    drop sequence sequenceName;(删除序列)

    10、tcl transaction control languge(事务控制语言)

    ​ 事务的概念:数据库的最小操作单位;

    ​ 特性:

    ​ 原子性A,最小操作单位,不可分割;

    ​ 一致性C,事务内的所以操作,要么一起成功,要么一起失败;

    ​ 隔离性I,事务相互之间不影响;

        持久性D,事务生效之后,会永久保存在硬盘上;
    

    ​ (ACID)

    ​ 隔离级别:Oracle只有两种(已提交读与串行化)myslq有四个:未提交读,已提交读,可重复读,串行化;

    COMMIT;(提交事务)
    ROLLBACK;(回滚事务)
    SAVEPOINT;(保存点)

    ​ 执行更新语句后,不会立即生效,oracle会自动开启事务,等待提交或者回滚;

    ​ DDL执行之后,默认自带commit;

    例子:

    insert into student(id,name,age,gender) values(1,'eee',23,'male');
    savepoint s1;
    insert into student(id,name,age,gender) values(1,'eee',23,'male');
    savepoint s2;
    insert into student(id,name,age,gender) values(1,'eee',23,'male');
    savepoint s3;
    insert into student(id,name,age,gender) values(1,'eee',23,'male');
    savepoint s4;
    insert into student(id,name,age,gender) values(1,'eee',23,'male');
    
    rollback to s3;--回滚s3这个保存点,当某些语句出错误时,回滚到对应的处理;
    
    

    11、procedure(存储过程,多用于更新)

    ​ (会对数据库服务器造成很大压力,移植性差,所以越来越少使用,会将相应的逻辑代码放入java代码中去优化)

    ​ 创建语法:

    create [or replace] procedure procedureName--(创建或者覆盖)
    	(parameter list)--(参数列表)
    	is
    	local_varicable declare--(本地变量声明)
    	begin	
    	business statement;
    	end;
    

    ​ 简单例子:

    	create or replace procedure mypro
    	is
    	begin
    		dbms_output.put_line('hello procedure!!!');
    	end;
    

    ​ 有参数的例子:

    	create or replace procedure mypro2
    	(
        i [in/out/in out] int default 1,--这里的类型不能类似varchar2(50),括号不能用-->varchar2;数据类型前可加形参的模式
        j int default 2 --可设默认值,设置默认值后调用可以不传参数,不然必须传参数
        )
    	is
    	s int;
    	begin
    		s:=i+j;
    		dbms_output.put_line(s);
    	end;	
    	call mypro2(3,4);--结果为7
    	call mypro2();--结果为3
    	call mypro2(j => 5);-- 名称表示法"=>" 修改默认值,结果为6
    

    ​ 调用时使用call procedureName;

    ​ drop procedure procedureName(删除存储过程)

    形式参数(存储过程,函数都有)
    参数的三种模式

    ​ IN mode:默认的模式,只读模式;这个模式的参数是只读的,存储过程开始调用的时候,将实参的值赋给形参。在整个存储过程的内部,in模式的形参,不可更改,为常量。(不能作为赋值的目标)in模式的参数不会影响实参;

    ​ OUT mode:只写,必须手动指定。在存储过程调用之前,out模式的形参是根据他的数据类型取默认值(null),当存储过程调用完后了之后,会将形参的值赋给实参;out模式的实参是不能为常量的;

    ​ IN OUT mode:手动指定,in与out模式的结合体;

    参数的传递方法

    ​ 位置表示法:按照实参的顺序匹配对应的形参

    ​ 名称表示法:(形参的名字=>实参)

    ​ 混合表示法:

    ​ 例子:(求学生表中全班的平均年龄,还有男,女某一个性别人数总和)

    create or replace procedure mypro4
    (
    gen in varchar2,
    avgage out number,
    gendercount out int
    )
    is
    begin
    	select avg(age) into avgage from student;
    	select count(1) into gendercount from student where gender=gen;
    end;
    
    declare
    	gender varchar(50):='male';
    	avga number;
    	gcount int;
    begin
    	mypro4(gen => gender,avgage => avga,gendercount => gcount);
    	dbms_output.put_line('性别为:' || gender || '人数总和是:' || gcount);
    	dbms_output.put_line('全班平均年龄为:' || avga);
    end;
    

    12、function(函数多用于查询)

    ​ (函数与存储过程在结构上的区别就是函数可以有返回值)

    create [or replace] function functionName
    (parameter list)
    retrun datatype--返回值数据类型
    is
    local_varicable declare--(本地变量声明)
    begin	
    business statement;
    end;
    
    select functionName() form dual;--调用
    drop function functionName();--删除函数
    

    function内部不能执行更新语句,procedure内部可以执行更新语句;

    procedure的事务跟调用事务是一起的,但是,如果procedure的内部存在commit语句的话,会分割为两个事物,则procedure的事务单独提交;

    简易例子:

    create or replace function mufun
    retrun int
    begin
    	dbms_output.put_line('hello myfunction');
    	return 1;
    end;
    
    --计算和         
    create or replace function mufun2
    (
    i in int,
    j in int
    )
    retrun int
    is
    begin
    	return i+j;
    end;
    select mtfun2(2,3) from dual;
    
    --某性别的总人数
    create or replace function mufun3
    (
    gen varchar2
    )
    retrun int
    is
    cc int;
    begin
    	select count(1)form student where gender=gen;
    	retrun cc;
    end;
    select mtfun3('male') from dual;
    
    oracle内置的函数(其他数据库不一定有效)
    数值/数学函数:(常用的几个)

    ​ ABS(); 求绝对值

    ​ CEIL(); 向上取整

    ​ FLOOR(); 向下取整

    ​ MOD(); 取余

    select mod(13,4) from dual;--结果为1
    select mod(13.4,4) from dual;--结果为1.4
    select mod(-13,4) from dual;--结果为-1
    select mod(13,-4) from dual;--结果1
    

    ​ SQRT();求平方根

    字符函数

    ​ CONCAT(a,b); 字符串连接(与||效果一样);

    ​ CHR(); 传一个数字进去,返回相应编码的字符;

    ​ INITCAP(); 每一个单词首字母大写;

    ​ LOWER(); 转换为小写;

    ​ UPPER(); 转换为大写;

    ​ L/RPAD(); 在字符的L左边/R右边使用某些字符进行补全到指定长度字符;

    select LPAD('Page 1',15,'*.') from DUAL;
    --结果为*.*.*.*.*Page 1
    

    ​ L/RTRIM(); 去除字符左/右边指定的字符,当遇到不是指定字符后将会停止;

    ​ TRIM(); 可以去头或者去尾,也可以都去;

    select LTRIM('<======>BROWNING<======>','<>=') from DUAL;
    --结果为BROWNING<======>
    

    ​ REGEXP_REPLACE(); 与正则表达式相关;

    ​ SUBSTR(); 根据字符为单位长度,截取字符串;

    ​ TRANSLATE(); 关键字屏蔽,字符转换;

    select translate('abacadefgtttt','abcdefg','123456') from dual;
    --结果为12131456tttt,将第二个字符串一个一个对应的转换为第三字符串的字符,如果第二个字符有多出的会被省略,可以理解为替换为null;
    
    转换函数
    null函数
    系统环境函数
    日期函数

    ​ extract(datetime);提取时间里面的信息,时分秒等;

    select extract(year from birthday) from student where id=1;
    select extract(day from sysdate)from dual;
    

    ​ sysdate; 返回操作系统的时间,后面不用加括号;

    ​ current_date; 根据时区返回系统时间,后面不加括号;

    ​ add_months; 添加月份,负数为减少;

    select add_months(sysdate,1) from dual;--月份加一
    select add_months(sysdate,-1) from dual;--月份减一
    

    ​ months_between; 求两个日期间隔多少个月,返回的是浮点数;

    ​ next_day; 某个日期的下个星期几;

    ​ to_char(); 将对应的日期转换为对应的格式;

    select to_char(sysdate,'YYYY"年"MON/DD HH/MI/SS') from dual;--格式中如果有中文需要加双引号引起;
    

    ​ trunc(); 传入一个日期,指定一个日期属性,如年份year,则除年份外其他属性都清除掉,回到原点,x月y日回到1月1日;

    13、trigger(触发器)

    定义:

    ​ 触发器跟存储过程一样,是一个PL-SQL单元块,存储在数据库里。但是触发器不能被显式的调用;

    ​ 触发器是可以启用和禁用的,默认创建时处于启用状态;

    ​ 当指定的事件发生的时候,触发器就会被oracle调用执行,那么这个过程称之为触发器触发(fires)。

    组成:

    ​ 触发事件:触发器要执行的指定事件;(DML触发器指定的触发事件就是DML操作,更新(insert,delete,update)语句)

    ​ 触发目标:触发器指定的事件在什么对象上执行,可以是table,view,schema(用户),database;

    ​ 触发时机:触发器在指定事件之前还是之后执行;

    ​ 触发频率:分为两种,行级触发器与语句级触发器;

    ​ 触发条件:在触发器定义中,通过when子句,指定触发器触发的条件。

    创建:
    create or replace trigger triggerName
    before | after | instead of --触发的时间
    INSERT or UPDATE[of column,...] or DELETE ON tableName--多个的话加or;update有一点区别,加of columnb表示对某一个字段进行修改,多个字段加逗号
    [referencing clause]
    [for each row ]
    begin
     business statement;
    end;
    
    例子:
    --删除表,打印
    create or replace trigger mytrigger
    before delete on student
    for each row
    begin
     dbms_output.put_line('delete a row on student');
    end;
    
    delete from student;
    
    
    --删除表数据时,将删除的数据插入到备份表中
    create or replace trigger mytrigger
    after delete on student
    referencing old as oo
    for each row
    begin
    	insert into student_back(id,name,age,gender)
    	values(:oo.id,:oo.name,:oo.age,:oo.gender);
    end;
    
    delete from student where id = 1;
    --referencing old/new as name(可以对下面的语句进行改名,不该默认为old与new)
    --:old(执行删除语句时,引用即将删除的数据)
    --:new(执行插入语句时,引用即将插入的数据)
    
    
    create or replace trigger mytrigger
    before update of name on student--更新name这一列时才起作用
    referencing old as oo new as nn
    for each row
    begin
    	dbms_output.put_line('old name:' || oo.name);
    	dbms_output.put_line('new name:' || nn.name);
    end;
    
    update student set age = 100 where id=1;--这条不会触发
    update student set naem = "sadad" where id=1;--这条语句执行才会触发
    

    14、view(视图)

    ​ 保存的就是一个sql语句;类似创建一个中间表方便查询,简化查询,即当一个查询语句十分复杂时,将结果放入视图作为中间表,查询起来更方便;在视图中进行更新操作会影响到原表,所以可以在创建视图时可以在语句后加一个with read only;

    create view viewName as 语句 [with read only];

    ​ 当需要连接多个表进行查询的时候,导致其查询语句十分复杂,这时就可以将这条查询语句放进视图中,再次查询就可以通过视图进行查询,简化查询;

    15、index(索引,为了增加查询速度)

    ​ 表中的数据量很大时,需要最快搜索到某一条记录,怎么做?

    ​ 首先,我们需要知道根据什么进行查询数据;如果是根据id主键进行查询,因为id已经排好序,所以查询会比较快,只需要将数据按合适的分组进行查询就可以了;但如果是别的字段,我们需要将id与这个字段提取出来放在另一个表中,然后对这个字段进行排序和分组查询,查询到这个字段后,在根据其id去找原表的数据,这就是索引的原理;

    ​ 百分之八十查询慢的问题,都可以通过使用索引来优化;使用索引时要使用后置匹配,前置匹配会导致索引失效;

    ​ 索引也有缺点,当索引中的数据在原表中被修改,那么索引中也要改,这样反而会影响更新的性能,所以一般在索引里的值不常改;但是如果一定要改,这个时候涉及到一个术语-- 数据归档,当数据中有某一些数据是很久之前的,一般不会再去修改的时候,这时会将这些数据定死/归档,或者专门移到另一个表中,然后再建立索引去查询;

    16、exception(异常)

    ​ 与java作用一样,为了不让语句异常终止;

    ​ 捕获异常

    declare
    begin
    exception	--捕获指定异常名称的异常,然后执行下面语句
    	when exceptionName then
    		statement;
    end;
    

    ​ 手动引发异常

    RAISE 异常名字:提示信息--类似java中的throw
    

    ​ 例子:

    declare
    	i int := 0;
    begin
    	i :=5/i;
    exception
    	when ZERO_DIVIDE then
    		dbms_output.put_line('除数不能为零!');
    end;
    

    ORACLE DBMS

    容灾,读写分开,集群等;

    备份-->import导入 export导出;

    grant ,赋予权限,用户不具备删库删表的权限,避免删库跑路;只有逻辑删除,没有物理删除,标记删除的数据,实际上每条数据进入数据库中不会被删除;我们只有查询更新的权限。

  • 相关阅读:
    求最大子数组02
    求最大子数组
    第3周学习进度
    四则运算3
    第2周学习进度
    构建之法阅读笔记02
    四则运算2及单元测试
    四则运算1
    第1周学习进度
    构建之法阅读笔记01
  • 原文地址:https://www.cnblogs.com/zzdbk/p/14274936.html
Copyright © 2011-2022 走看看