【网学网提醒】:网学会员鉴于大家对十分关注,论文会员在此为大家搜集整理了“sql指令集”一文,供大家参考学习
ORACLE学习笔记
创建表空间
1.创建表空间的指令。名称:user1;地址;初始大小;是否自动扩展;扩展大
小;最大尺寸
createtablespaceuser1datafile'f:\oracle\wuzheren\user1_data.dbf'size10mautoextendon(off)next2mmaxsize30m(unlimited)2.查看表空间创建成功的指令
selectfile_name,tablespace_namefromdba_data_filesorderbyfile_name3.查看表空间。
selecttablespace_name,status,allocation_typefromdba_tablespaces4.删除表空间user1(同时删除文件加including)
5.查看所有的表空间信息
selecttablespace_name,status,allocation_typefromdba_tablespaces6.查询每个用户的默认表空间
selectuser_id,username,default_tablespacefromdba_users7.修改数据库的默认表空间(user1)
alterdatabasedefaulttablespaceuser1
8.修改表空间名称(user1—user10),不对数据文件产生影响,不可对系统表空
间进行重命名。
altertablespaceuser1renametouser10创建数据表(主要介绍sql语言)1.创建数据表(t_user)
createtablet_user(user_idnumbernotnull,user_namevarchar2(20)notnull,user_emailvarchar2(20))
2.查看数据表所属的表空间(未成功=为选定行)
selecttable_name,tablespace_namefromuser_tableswheretable_name='t_user'3.查看数据表信息(t_user)
describet_user4.修改数据表结构(t_user的user_email—email)
altertablet_userrenamecolumnuser_emailtoemail5.修改列的属性(1个或多个)
altertablet_usermodify(user_namevarchar2(20),user_emailvarchar2(30))6.为表添加列
altertablet_useradd(beizhuvarchar2(10))
7.删除表中的某列(需要增加关键字column)
altertablet_userdropcolumnremark
8.修改表名(表本身的属性,不可轻易修改一个表名,表明为操作标识,会影响
已有程序的运行)
altertablet_userrenametot_users9.删除数据表
droptablet_user10.删除表约束
droptablet_usercascadeconstraints临时表
——会话级临时表
1.创建会话级临时表(当前事务提交时,保留数据)
createglobaltemporarytabletmp_user_session(user_idint,user_namevarchar2(20),user_emailvarchar2(30))oncommitpreserverows2.向临时表中插入数据
insertintotmp_user_session(user_id,user_name,user_email)values(1,'alex','alex@126')3.查表中数据,验证是否插入正确(tmp_user_session)select*fromtmp_user_session
4.提交数据修改,结束会话
commit
~~会话级临时表仅存在当前会话中,一旦会话结束,数据库将自动清理其中的数据(相当于使用turncatetable命令),各会话之间的数据也是相互独立、互不影响的。
——事务级临时表
1.创建事务级临时表,并插入两条测试数据
createglobaltemporarytabletut(idint,namevarchar2(20),emailvarchar2(30))oncommitdeleterows;
insertintotut(id,name,email)values(1,'boy','boy@126');insertintotut(id,name,email)values(2,'girl','girl@126')2.提交数据,结束事务
rollback
ORACLE学习笔记
~~事务级临时表的数据仅在当前事务有效,一旦事务结束,所有数据会自动清空。查看临时表在数据库中的信息
1.查询表空间信息(注意大小写)→→→临时表的表空间为空
selecttable_name,tablespace_namefromuser_tableswheretable_name='T_USER'ortable_name='TUT'ortable_name='TUS'
2.查询临时表的不同(名称,是否临时表,类型)
selecttable_name,temporary,durationfromuser_tableswheretable_name='T_USER'ortable_name='TUS'ortable_name='TUT'~~临时表的应用场景~~
1.大表分割2.解决并行问题3.作为数据缓存——特殊的表dual
1.查询dual表→→→dual仅有一列dummy字符长度可变字符串允许为空
DESCDUAL~~dual表应用场景~~
1.获得当前日期(sysdate是系统函数,返回当前日期)
selectsysdatefromdual
2.进行数学运算
select3*4+12asresultfromdual
3.实现序列运算→→→每执行一次,序列自动加一
selectt_user_sql.nextvalfromdual
约束
主键约束
1.创建主键约束
createtablestudent(idnumberprimarykey,name
varchar2(20),birthdaydate,addressvarchar2(50),phonevarchar2(20))
2.查看主键约束
1.查看约束
方法一:对象—右键—VIEW—KEYS方法二:select
table_name,constraint_name,constraint_type,statusfromuser_constraintswheretable_name='STUDENT'→→→(表名信息,
约束名信息,约束类型,当前状态)
2.如何获得主键的作用列
selectconstraint_name,table_name,column_namefrom
user_cons_columnswhereconstraint_name='SYS_C005145'→→→(约束名信息,表名信息,约束所在列)
3.测试主键约束
insertintostudent(id,name,birthday,address)values(1,'张三',to_date('1998-12-01','YYYY-MM-DD'),'人民路')
insertintostudent(id,name,birthday,address)values(2,'李四',to_date('1999-06-03','YYYY-MM-DD'),'人民路')→→→→→→无法成功插入,存在主键约束
4.
5.
6.
修改表的主键约束——表只能具有一个主键1.为表添加主键———未创建
altertablestmodify(idnumberprimarykey)
2.为表添加多列主键———逗号隔开
altertablestaddconstraintpk_stprimarykey(name,birthday,address)
3.删除主键
方法二:删除约束的语法来删除表的主键(表的约束有若干个,指定约束名称)
4.启用\禁用主键
禁用:altertablestdisableprimarykey插入两条信息
insertintost(id,name,birthday,address)values(1,'张三',to_date('1998-12-01','YYYY-MM-DD'),'人民路','010-22415109');
insertintost(id,name,birthday,address)values(2,'张三',to_date('1998-06-30','YYYY-MM-DD'),'人民路','010-22415130');
启用:altertablestenableprimarykey→→→ORA-02437:无法验证(SYSTEM.PK_ST)-违反主键
修改:updatestsetname='李四'whereid=2
5.重命名主键
查询oracle自动分配主键名称:
selectconstraint_name,table_name,constraint_type,statusfromuser_constraintswheretable_name='ST'
rename关键字重命名主键:
altertablestrenameconstraintsys_c005152topk_st;
~~主键应用场景~~
1.对于完整性要求比较高的数据表都应建立主键
2.对于经常按照某列进行查询的数据表,应该考虑建立主键3.考虑是否对外键有利
外键约束——两表之间的相互依存性创建外键约束1.建立外键
建立表cts和ods:
createtablects(idnumberprimarykey,name
varchar2(10),addressvarchar2(20),phonevarchar2(20));createtableods(o_idnumberprimarykey,idnumber,g_namevarchar2(20));
建立ods到cts的外键关联:(注意大小写)
altertableODSaddconstraintfk_ocforeignkey(id)
2.查看外键信息(表名,约束名,约束类型,与该约束关联的其他约束名)
selecttable_name,constraint_name,constraint_type,r_constraint_namefromuser_constraintswheretable_name='ODS';
查询关联约束信息:select*fromuser_constraintswhereconstraint_name='SYS_C005153'
3.验证外键约束的有效性(只向子表插入信息)
insertintoods(o_id,id,g_name)values(1,1,'FABRAK');→→→→→→ORA-02291:违反完整约束条件(SYSTEM.FK_OC)-未找到父项关
键字
先父表后子表:
insertintocts(id,name,address,phone)values(1,'王厚胜','哈工大','13654555062');
insertintoods(o_id,id,g_name)values(1,1,'FABRAK');
4.修改字表数据验证外键约束的有效性
updateodssetg_name='fuck'whereo_id=1;→→运行、查询正常updateodssetid=3whereo_id=1;→→ORA-02291:违反完整约束条
件(SYSTEM.FK_OC)-未找到父项关键字→→→→→→当修改非外键列的数据时,不会受外键影响;但是当修改外键列为不合理数据时,外键约束禁止该动作的运行。5.修改父表数据验证外键约束的有效性
修改父表数据:updatectssetid=3whereid=1;→→ORA-02292:违反完整约束条件(SYSTEM.FK_OC)-已找到子记录
→→→→→→父表的主键列,是子表的外键关联列,修改造成目标值与原值不同,造成子表数据丢失,故报错。
删除父表:deletefromctswhereid=1;→→ORA-02292:违反完整约束
条件(SYSTEM.FK_OC)-已找到子记录
删除整个表:droptableCTS;→→ORA-02449:表中的唯一/主键被外键引
用
→→→→→→即使数据表中没有数据亦不能在删除子表之前删除父表,因为外键约束已经将子表与父表绑定在一起,父表将无法自由删除。~~外键约束的两个方面~~
ORACLE学习笔记
①对数据的约束,父表的数据和子表的数据必须保持一致
②对表之间关系的约束,子表依附于附表存在,一旦建立关联关系,父表将不能在删除子表前删除。级联更新与级联删除1.级联更新
插入数据:
insertintocustoms(c_id,c_name,c_add,c_phone,email)values(1,'王鹏','哈工大机电
','13613608765','wangpeng@126');
insertintoorders(o_id,c_id,goods)values(1,1,'皮鞋');
修改延迟校验外键约束表的建设(执行一次提交动作)→→→→保持提交数据的一致性
updatecustomssetc_id=3wherec_id=1;updateorderssetc_id=3wherec_id=1;commit;
查看更新结果:
selectc_id,c_name,c_add,c_phone,emailcontratorfromcustoms;
selecto_id,c_id,goodsfromorders;
2.级联删除
创建外键约束时指定延迟校验,
并且延迟校验的时机为事务提交,可通过先删除主表数据,然后删除子表数据的方式实现级联跟新的效果(ondelete)
创建级联删除外键约束:
altertableordersaddconstraintfkforeignkey(c_id)referencescustoms(c_id)ondeletecascade;
删除主表中的记录,子表自动删除:
deletefromcustomswherec_id=3;
修改外键属性
1.重命名外键(rename)
altertableordersrenameconstraintfktofuck;
2.禁用\启用外键
禁用:altertableordersmodifyconstraintfuckdisable;启用:altertableordersmodifyconstraintfuckenable;
检查状态:
selectconstraint_name,statusfromuser_constraintswhere
constraint_name='FUCK';
3.
novalidate只是一种临时状态
4.删除外键—使用删除约束的统一语法:altertabledropconstraint
altertableordersdropconstraintfuck
~~外键使用~~
①严格遵循父子关系的数据表应该使用外键②将应用程序中的父子关系转移到外键约束③不要过分使用外键
唯一性约束——唯一的标识一行(主键设计为表示惟一一条记录,唯一性约束保证列自身值的唯一性)
创建唯一性约束——unique1.创建唯一性约束
创建表时添加唯一性约束:
2.查看唯一性约束
selecttable_name,constraint_name,constraint_type,status
altertableusersmodifyconstraint
2.删除唯一性约束
altertableusersdropconstraintu_phone;altertableusersdropconstraintu_name;
3.重命名唯一性约束(自动分派为SYS_C005161)
altertableusersrenameconstraintSYS_C005161tou_email;
4.禁用\启用唯一性约束启用:altertableusersenableconstraintu_name;\altertableusersmodifyconstraintu_nameenable;禁用:altertableusersdisableconstraintu_name;\altertable
usersmodifyconstraintu_namedisable;~~唯一性约束的使用~~
可建立在列或列的组合上,作为逐渐约束的补充,在业务逻辑上保证记录的唯一性往往采用唯一性约束来实现检查约束
创建检查约束(关键字check)①创建检查约束
createtablestudent(idnumberprimarykey,name
尝试输入合法数据:
insertintoemplyeesvalues(1,'王朋','one',730)insertintoemplyeesvalues(2,'王鹏','two',500)insertintoemplyeesvalues(3,'赵娟','three',340)
非法数据:
insertintoemplyeesvalues(4,'邓健','three');→→→→ORA-00947:
没有足够的值
修改检查约束1.2.删除
altertableemplyeesdropconstraintc_sa;3.重命名(c_na→→check_na)
altertableemplyeesrenameconstraintc_natocheck_na;4.禁用\启用
禁用:
altertableemplyeesdisableconstraintc_sa;altertableemplyeesmodifyconstraintc_sadisable;
ORACLE学习笔记
启用:
altertableemplyeesenableconstraintc_sa
;
altertableemplyeesmodifyconstraintc_saenable;
~~检查约束的使用~~
通过很灵活的约束条件完成约束任务,但不能过多使用检查约束,尤其是复杂的检查约束,因更新数据库时会进行约束检查浪费大量资源。默认值约束
创建默认值约束——对象为列,每列只能有一个默认值约束(关键字default)1.2.
3.默认值的使用
insertintopo(id,name,price)values(1,'王朋',100);insertintopo(id,price)values(1,100);→→→→未设置验证,只输入指定项亦是可以的。
4.使用函数作为默认值
尝试插入数据:
insertintosss(id,name,price)values(1,'王朋',
30);insertintosss(id,name,price)values(1,'王鹏',30);→→ORA-00001:违反唯一约束条件
insertintosss(id,name,price)values(1,'王朋',30);insertintosss(id,name,price)values(2,'王朋',30);→→ORA-00001:违反唯一约束条件
insertintosss(id,name,price)values(1,'王朋',30);
insertintosss(id,name,price)values(2,'王鹏',60);→→ORA-02290:违反检查约束条件
修改默认值约束
1.2.删除默认值约束
altertablesssmodifypricenumberdefaultnull;
3.视图—存储查询,但不会存储数据(物化视图除外),可进行查询、插入、更新和删除数据关系视图内嵌视图对象视图物化视图关系视图
建立关系视图
①建立关系视图创建测试数据表:
createtableemply(idnumberprimarykey,f_name
varchar2(4),l_namevarchar2(4),provincevarchar2(10),cityvarchar2(10),salarynumber);
插入数据:
insertintoemplyvalues(1,'张','军','广东','深圳',3000);insertintoemplyvalues(2,'刘','新','广东','广州',4000);insertintoemplyvalues(3,'王','一帆','广西','桂林',3800);insertintoemplyvalues(4,'周','峰','江苏','苏州',4000);insertintoemplyvalues(5,'徐','佳林','浙江','杭州',2900);
②查看视图定义(user_views查询所有用户的视图定义)
selecttextfromuser_viewswhereview_name='VW_EMPLY';
③查看试图内容
select*fromvw_emply;
1.修改视图
尝试修改视图(增加salary)
2.删除视图
dropviewvw_emply;
联接视图——相对于多个表而言的视图
创建视图:
createtableemply(idnumberprimarykey,f_namevarchar2(4),l_namevarchar2(4),salarynumber);
createtableem_salary(s_idnumber,s_pricenumber,sale_bynumber);插入数据:
insertintoemplyvalues(2,'王','朋',400);
insertintoem_salary(s_id,s_price,sale_by)values
(2,100,2);编译视图
查看视图状态信息(user_object包括数据库中所有对象信息,包括表、视图、
约束等)selectobject_name,statusfromuser_objectswhere修改表的结构:
altertableemplyadd(agenumber);
——查询:INVALID无效,因为基础表发生变化,需重新编译视图
重新编译视图:
alterviewvw_emcompile;(亦可以执行一次对视图的查询操作)
——修改数据表的结构才会影响视图的有效性,修改数据并不会影响数据的有效
性,但是并不是修改数据结构重新编译后就可以正常运行,例如当重命名基础表的列名,而该列又在视图定义中。
使用force选项强制创建视图——视图的基础表未创建前,仍希望可以创建基于不存在表的视图,可使用force强制创建。创建:
createorreplaceviewvw_emasselectbook_name,authorfrombook;
→→→→ORA-00942:表或视图不存在
createorreplaceforceviewvw_emasselectbook_name,authorfrombook;
→→→→Warning:Viewcreatedwithcompilation
errors
查询是否创建成功:
selectobject_name,statusfromuser_objectswhereobject_name='VW_EM'andobject_type='VIEW';
——视图虽然创建,但仍不可用,当基础表创建后,视图方可正常使用。利用视图更新数据(数据必须是直接从基础表中获得的)
ORA-01779——试图修改的列在基础表中的映射并没有唯一性约束。
ORA-01733——试图修改列为虚列,没有基础表的列与之对应。查看视图列的可更新情况:
selecttable_name,column_name,updatable,insertabledeletablefromuser_updatable_columnswhere
table_name=’vw_books’;——对查询结果进行操作,尽管某些数据的列项为空withcheckoption选项(创建视图时常用选项之一,启用该选项,则数据库保证视图在数据更新之后与更新之前的结果集相同)
ORACLE学习笔记
创建基础表,并插入数据:
createtablebook(idnumber,namevarchar2(10),authorvarchar2(10),pressvarchar2(20),p_datedate);
insertintobookvalues(1,'围城','钱钟书','人民文学出版社',to_date('2006-4-9','yyyy-mm-dd'));
在对象的概念之下,数据仍然是存储于关系表中的)要创建对象,首先要建立对象类型创建对象employee:
createtypeemployeeisobject(employee_idnumber,employee_namevarchar2(20),locationvarchar2(50),salarynumber)
创建对象视图:
createorreplaceviewvw_bookasselect*frombookwhereid=3;createorreplaceviewov_employeesofemployeewithobjectoid(employee_id)
创建视图:
通过视图更新数据:
updatevw_booksetid=4wherename=’平凡的世界’;——查询视图为空,因为视图的查询条件限制了查询内容
where子句违规~~关系视图~~①??保障数据安全性②??数据整合③??数据透明性内嵌视图内嵌视图的使用1.利用内嵌视图进行查询(可使用别名)2.利用内嵌视图更新数据表3.删除和插入~~内嵌视图~~①内嵌视图、临时表、关系视图的使用场景
内嵌视图并不是真正创建视图,故不会进行大量的I/O操作,节省大量数据库资源,若临时使用另外的查询结果时建议使用内嵌视图,当背多处使用(可复用性高)应考虑使用临时表或者关系视图。②分辨内嵌视图与子查询
在sql语句中,代替了表的位置的查询即为内嵌视图,例如from或into关键字之后,注意内嵌视图的定义必须用小括号括起来。
对象视图(虽然可以从对象中获取数据,就像数据真实存储于对象中一样。但是
asselectemployee_id,last_name||first_name,province||city,salaryfromemployees查询对象视图:
descov_employees;查询对象视图信息:selectview_type,view_name,oid_textfromuser_viewswhere
view_name='ov_employees'ORA-01730:指定的列名数无效——注意对象与源表得的一一对应基础表中获得的各列数据将和对象中的属性按照定义顺序一一对应,不能颠倒,否则:ORA-00932,并且,数据类型需要一致,否则将报错。对象试图可以进行增删改查操作,类似于关系视图。~~关系视图、内嵌视图和对象视图,实际都是通过定制查询,并利用查询定义获取数据,三种视图不会直接存储数据,每次操作时,都会进行编译。物化视图——该视图实际存储数据——对于大数据表的处理显得重要,可将统计结果存储在物化视图中,节省数据库资源和时间,但不适合统计更新频繁的数据。物化视图的使用1创建实验表,并加入数据:
createtablesales(idnumberprimarykey,namevarchar2(10),pricenumber,quantitynumber,s_monthvarchar2(4),sale_bynumber);insertintosalesvalues(6,'皮鞋',100,4,'3月',2);创建物化视图
creatematerializedviewmv_sales——创建物化视图,注意无replacebuildimmediate——立即编译
refreshoncommit——基础表修改后自动更新视图enablequeryrewrite——启用查询重写功能
ORACLE学习笔记
asselects_month,sum(price*quantity)fromsalesgroupbys_month;——统计要求查询数据:
select*frommv_sales;
2.查看物化视图信息(user_mviews和user_objects)
selectmview_name,queryfromuser_mviewswheremview_name='MV_SALES';
selectobject_name,object_type,statusfromuser_objectswhereobject_name='MV_SALES';→→→物化视图创建视图的同时也创建了一个同名的物理表,而物理表才是真正存储数据的地方
物化视图的数据加载
buildimmediate该项用于立即加载物化视图的数据,亦即在创建物化视图的同时,立即根据定义从基础表中获取数据,并将数据添加到物化视图中,选项builddeffered则表示延迟加载数据。使用延迟加载是必要的,尤其是在基础表数据量巨大,数据使用高峰期时,后造成客户端的延迟。为在后续的开发中使用物化视图可采用延迟加载数据的策略,类似于创建一个空表,并不向表中插入数据,但可以成功的在开发中引用。物化视图的数据更新
插入数据,commit后,物化视图自动更新
物化视图的自动更新与关系视图的自动更新不同。物化视图的自动更新,是将更新后的数据存储起来,而关系视图则每次都会查询基础表;但物化视图的自动更新对于基础表的大量频繁更新是不利的,因为频繁的更新会占用大量数据库资源,因此物化视图应使用在读取频繁、更新较少的情况下。查询重写enablequeryrewrite用于启用查询重写,查询重写是指oracle对基础表的查询,按照优化的原则,查找恰当的物化视图,如果获得优化视图,则将查询转化为对物化视图的查询。
利用物化视图实现查询重写(存在物化视图,直接查询物化视图;若不存在,则查询基础表)删除物化视图
~~视图的主要功能~~1.增强安全性
2.组装数据3.封装复杂查询4.提供建模模型5.
提高响应速度
如何获取某个表的列selecttable_name,column_name,data_typefromuser_tab_colswherelower(table_name)=’teacher’;user_tab_cols——oracle已定义的视图
lower(table_name)——oracle存储对象时,会采用大写形式,此函数将列值统一为小写形式
函数与存储过程
函数
~函数简介
函数可以包含传入参数,函数的语句块进行实际的处理动作,并最终返回值。只要是两类:一类是系统函数,即oracle已经定义好的函数,一类是自定义函数,即用户根据需要自行定义的函数。自定义函数时应注意以下几个方面:
①函数与功能的划分。应该首先明确函数的功能。每个独立的功能应该使用
单独的函数实现,若多个功能在同一个函数中实现,不仅使代码复杂化,增加维护成本,更重要的是,不易最大化实现复用,故首先将功能划分清晰,针对功能实现函数。
②函数的参数。函数的传入参数可以没有,若有,一定要明确其数据类型。
函数传入参数不能在函数内部进行修改(不必担心函数内部对参数的修改会影响调用者环境)
③函数的返回值。函数必须有返回值,并且返回值必须在函数的结尾处使用
return命令返回。返回值的类型可以是字符串、数值型、数组或者对象类型,但是不能返回记录集合(记录和记录集并不是oracle的数据类型)
)
ORACLE学习笔记
每条语句以;结尾,begin和end是一个语句块,在endget_hello_msg后;2.在数据字典中查看函数的信息
selectobject_name,object_type,statusfromuser_objectswherelower(object_name)='get_hello_msg';
selectname,type,line,textfromuser_sourcewhere
lower(name)='get_hello_msg';——函数或存储过程的名称;函数或存储过程的标识类型;代码的行号;user_source为每行源码的实际内容
3.查看函数的返回值开启服务器输出:
setserverouton;
代码:
declaremsgvarchar2(20);—声明变量begin
msg:=get_hello_msg;—赋值为函数的返回值
dbms_output.put_line(msg);—控制台上打印出msg的内容end;
一旦函数创建则可以像其他函数一样使用该函数,查询get_hello_msg函数
selectget_hello_msgmsgfromdual;——直接使用select语句查询
get_hello_msg的返回值,并指定别名msg~函数中的括号(当函数需要传入参数时,参数列表必须使用小括号括起来,但是当函数没有参数时,小括号可以省略。当函数没有括号时,在形式上和变量相同,那么有可能产生变量冲突)变量与变量冲突:declaremsgvarchar2(20);get_hello_msgvarchar2(20);begin
get_hello_msg:='welcomemessage';msg:=get_hello_msg;
dbms_output.put_line(msg);end;
→→→→welcomemessage
不要省略函数的下括号,不要声明一个与函数同名的变量,否则系统将无法正确引用该函数。
~函数的参数(带参数函数的创建和使用)
createorreplacefunctionget_tax(p_salarynumber)returnnumberasbegindeclare
tax_salarynumber;begin
tax_salary:=p_salary-2000;iftax_salary<=0thenreturn0;endif;
iftax_salary<=5000then
returntax_salary*15/100-125;endif;end;endget_tax;
测试数据:
selectget_tax(6000)taxfromdual;
~函数的确定性(每次调用函数,oracle总是根据传入的参数,执行相同的步骤,
并返回最终值。函数的确定性是指传入的参数一定,无论函数被调用多少次,都会返回相同的值。对于确定性的函数,在定义时,可以使用deterministic选项,以告知oracle创建确定函数。deterministic选项用于指定新建函数为确定函数,注意:选项定义应该置于返回值的定义之后,否则,编译将报错)`典型的函数举例建立sd表,插入数据,如何获得学生的名字
而存储过程更适合执行对数据库的更新,尤其是大量数据的更新。优点如下:1.提高数据库执行效率。使用SQL接口更新数据库,如频繁连接数据库,将非常
耗时和耗费资源,将工作交由存储过程完成,减少数据库连接频率。2.提高安全性。存储过程是作为对象存在于数据库中的,可通过对存储过程分配
权限来控制操作的安全性。同时,使用存储过程实现了数据库操作从编程语言转移到了数据库中。3.可复用。
~创建存储过程(实现数据库增删改查操作,也可以实现复杂运算,但不能够直接实现数据库定义语言)
2.查看存储过程在数据字典中的信息
selectobject_name,object_type,statusfromuser_objectswherelower(object_name)='update_sd';
select*fromuser_sourcewherelower(name)='update_sd';
3.执行存储过程
~存储过程的参数——OUT参数(函数可以有返回值,存储过程并没有现实的返回值,但是可以通过OUT参数获得存储过程的处理结果)
过程实际需要两个参数。
~存储过程的参数——INOUT参数(既可以作为传入参数,也可以作为传出参数,
例子:交换两个变量的值
createorreplaceprocedureswp(i_o_p1inoutnumber,i_o_p2inoutnumber)asbegindeclarepnumber;begin
p:=i_o_p1;i_o_p1:=i_o_p2;i_o_p2:=p;end;endswp;
输入数据,开始:
declarep1number:=25;p2number:=52;beginswp(p1,p2);
dbms_output.put_line('p1='||p1);dbms_output.put_line('p2='||p2);end;
—~INOUT参数的确带来了很多便利,但也存在弊端,首先存储过程可能为多个用户调用,那么针对输出参数的变量奖杯频繁且无规律的更新,控制该变量将变得十分困难,此外,具有输出的性质,将不能使用常量来传入参数,否则会编译报错,除非必要建议选用IN或OUT参数单向参数
~存储过程的参数——参数顺序(与其他编程语言一样,存储过程的参数顺序同样重要)
意思是将参数in_name赋值为“柳青”——虽然参数顺序和存储过程定义的的顺
序不同,但由于使用了参数名称,仍可以成功处理。对于IN参数虽然可以利用名
——首先使用位置表示法,再使用名称表示法是合理的。
~存储过程的参数——参数的默认值(存储过程的参数有很多,但对于某些用户来说,,部分参数是非必须的,可设定为默认值,以允许用户不为该参数传值只针对于IN,而OUT和INOUT则无默认值)~存储过程的参数——参数顺序总结
具有默认值的参数应该置于参数列表的末尾,因为有时需要省略该参数;没有默认值的参数可遵循“IN——OUT——INOUT”;有默认值的是可选参数,若用户没有输入参数,则只能采用名称表示法。
程序包(程序包可以将若干个函数或者存储过程组织起来,作为一个对象进行存储。程序包通常包括两部分:规范和主体。程序包可以包含常量和变量,包中的所有函数和存储过程都能够使用这些常量和变量)
~规范(程序包的公共接口,规范中一般定义公用的变量、需要组织到程序包中的
ORACLE学习笔记
所有函数和存储过程都会出现在规范中。其出现的形式为:仅定义名称和参数列表,但不包括实际处理语句。规范相当于面向对象编程中的接口——只定义方法名称和参数,并无真正实现方法)
1.创建程序包规范(关键字:createorreplacepackage)
createorreplacepackagepkg_sdassd_stringvarchar2(500);sd_agenumber:=18;
functionget_sd_stringreturnvarchar2;procedureup_sd(i_sd_idinnumber);procedureinsert_sd(i_sd_idinnumber,i_sd_nameinvarchar2,i_sd_ageinnumber);proceduredel_sd(i_sd_idinnumber);endpkg_sd;
2.在数据字典中查看程序包规范的信息
selectobject_name,object_type,statusfromuser_objectswherelower(object_name)='pkg_sd';→→→→VALID
select*fromuser_sourcewherelower(name)='pkg_sd';→→→→name、type、line、text;
~主体(正真实现功能的地方,但是主体必须遵从规范,实现规范中定义的函数和存储过程。类似于面向对象编程中的类必须实现接口中的所有方法一样,主体必须实现对应规范的所有函数和存储过程,否则将会出现编译报错)
1.创建程序包主体(关键字:createorreplacepackagebody)
createorreplacepackagebodypkg_sdas
ebdpkg_sd;→→→→报错PLS—00323,因为规范中声明的函数未在主体内实现createorreplacepackagebodypkg_sdasfunctionget_sd_stringreturnvarchar2asbegindeclarecursorcu_sdisselectnamefromsdorderbyid;sd_namevarchar2(10);rowstringvarchar2(500);begin
opencu_sd;
fetchcu_sdintosd_name;
whilecu_sd%foundloop
rowstring:=rowstring||sd_name||'、';fetchcu_sdintosd_name;endloop;
returnsubstr(rowstring,1,length(rowstring)-1);end;
endget_sd_string;
procedureup_sd(i_sd_idinnumber)asbegin
updatesdsetage=sd_agewhereid=i_sd_id;commit;endup_sd;
procedureinsert_sd(i_sd_idinnumber,i_sd_nameinvarchar2,i_sd_ageinnumber)asbegin
insertintosdvalues(i_sd_id,i_sd_name,i_sd_age);commit;endinsert_sd;
proceduredel_sd(i_sd_idinnumber)asbegin
deletefromsdwhereid=i_sd_id;commit;enddel_sd;endpkg_sd;
2.在数据字典中查看该程序包的主体信息
selectobject_name,object_type,statusfromuser_objectswhere
lower(object_name)='pkg_sd';→→→→
PKG_SDPACKAGEVALID
PKG_SDPACKAGEBODYVALID
~调用函数包中的函数/存储过程(对于程序包中的函数,可以直接在select语句进行调用,调用格式为package_name.function_name())调用程序包中的函数:
selectpkg_sd.get_sd_string()fromdual;
ORACLE学习笔记
调用程序包中的存储过程:
begin
pkg_sd.insert_sd(4,'王厚胜',30);end;
~程序包中的变量(程序包中的变量一般声明在规范中,而且可以被主体中所有函数/存储过程共享)
——~~——存储过程的应用非常广泛,可以用来处理非常复杂的问题。比较常用的一种是循环处理,有时将由一条语句可以处理的问题使用存储过程来解决可能是一种更好的策略
游标(作为数据库必须提供一种方便的访问数据的方法)
~游标简介(类似于编程语言中的指针,可以进行位置的移动,以访问结果集中每条记录,通过游标可以方便的访问当前记录。游标主要有两类:显示和隐式。显式游标可以被用户显示创建、打开、访问、关闭,即用户可以控制游标的整个生命周期;隐式游标无需用户全程控制,即可进行访问)
~显式游标(在使用时应遵循“创建—打开—访问—关闭”的步骤)
1.声明游标(关键字:declare,内容一般用sql语句来定义,本质是用来处理结果
集中的每条记录)2.使用游标
①如何使用变量获取游标信息
declare
cursorc_sd_id_nameisselectid,namefromsd;sd_idsd.id%type;sd_namesd.name%type;begin
openc_sd_id_name;fetchc_sd_id_nameintosd_id,sd_name;
whilec_sd_id_name%foundloop
dbms_output.put_line(sd_id||':'||sd_name);fetchc_sd_id_nameintosd_id,sd_name;
endloop;
closec_sd_id_name;end;
②
利用行类型获取游标信息
declarecursorcu_sdisselect*fromsd;studentsd%rowtype;begin
opencu_sd;
fetchcu_sdintostudent;whilecu_sd%foundloop
dbms_output.put_line(student.id||':'||student.name);fetchcu_sdintostudent;endloop;closecu_sd;end;
③使用带参数的游标
ORACLE学习笔记
endloop;closecu_st;end;
~隐式游标(相对于声明游标变量的显式游标而言。显式游标通常使用declare命令来声明;而隐式游标则无需这样。隐式游标不能直接被用户控制和使用——执行打开open、获取游标数据fetch、关闭close等。隐式游标有两种:使用oracle自定义的名为SQL的隐式游标和使用cursorforloop进行循环的隐式游标)1.SQL隐式游标(oracle为每个pl\sql的会话定义了一个名为sql的游标变量,可
以直接调用该变量)直接调用游标变量sql:
begin
ifsql%rowcount>0then
dbms_output.put_line('sql变量的rowcount属性大于零');endif;end;
→→成功执行:PL/SQLproceduresuccessfullycompleted每次执行数据库更新(DML)时,oracle都会自动更新该变量。Oracle自动更新游标变量:
begin
updatesdsetage=age+12;
dbms_output.put_line('共更新了'||sql%rowcount||'条记录');end;
SQL变量是被oracle自动声明,但并不能被用户控制,这反映其隐式变量的特点,不能使用fetch命令进行显式操作。SQL隐式变量只能用于更新、删除等操作之后的属性信息获取。
2.sursorfor游标(sql游标可以应用于更新及删除数据表中的数据,为了能够处
理select语句获取的记录集合,oracle还提供了另一种隐式游标—cursorfor游标。利用该游标可以像使用普通循环语句一样来循环处理select语句获得的每一条记录)
演示cursorfor游标的使用:
endloop;end;
利用for循环可以处理select命令获得的结果集,利用sql隐式变量可以处理update、delete等操作的结果,二者相互配合可以实现与显式游标相同的所有功能。3.隐式游标和显式游标
隐式游标和显式游标都可以实现对结果集的操作,相比之下,隐式游标不需要用户控制游标的声明、打开、获取和关闭,因此用户可以利用更少的代码实现同样的功能。而且,隐式游标的执行速度更快,在对游标的显式控制要求不高时,应尽量选择隐式游标。
~游标属性(游标属性反映了游标的当前状态,游标属性对于pl\sql编程有着极其重要的作用,逻辑判断时可以使用,4常用游标属性:
found—标识当前游标从结果中获得数据时,是够成功找到了纪录
notfound—found属性的对立面,当不能成功获得记录时,将返回true,否则返回false
rowcount—返回当前时刻已经获得了多少条记录isopen—判断游标是否处于打开状态,若游标打开则返回true,否则返回false。该属性被有标的open和close动作(对于隐式游标,oracle自动执行)更新
前三个属性,均被游标的动作fetch动作(对于隐式游标,oracle自动)更新演示如何使用4种属性监视游标状态:
declarecursorc_sdisselect*fromsd;stsd%rowtype;begin
ifc_sd%isopenthen
dbms_output.put_line('游标c_sd已经打开');else
dbms_output.put_line('游标c_sd未打开');endif;openc_sd;
ifc_sd%isopenthen
dbms_output.put_line('执行open后,游标c_sd已经打开');else
dbms_output.put_line('执行open后,游标c_sd未打开');endif;
ORACLE学习笔记
fetchc_sdintost;
定义已经确定。在整个程序运行过程中,游标的定义不能再更改,因此显式游标
dbms_output.put_line('第一次执行fetch后,rowcount的属性值为:'||和隐式游标统称为静态游标。为增强游标的灵活性,oracle提供—动态游标,即其c_sd%rowcount);定义在游标声明时没有设定,在打开时,可进行动态修改。动态游标又分为:强ifc_sd%foundthen类型动态游标和弱类型动态游标)dbms_output.put_line('第一次执行fetch后,found的属性为:true');1.强类型动态游标(指在游标声明时虽未设定其查询定义,但是已经指定了游标else的返回类型。游标的返回类型可以是oracle内置类型,也可以是自定义类型。dbms_output.put_line('第一次执行fetch后,notfound的属性为:声明一个强类型游标需要首先自定义一个refcursor的游标类型,然后利用该true');endif;
dbms_output.put_line('-------------------------------------------------------');loop
ifc_sd%foundthen
dbms_output.put_line('循环执行?¤?¤?¤,rowcount的属性为:'||c_sd%rowcount);
fetchc_sdintost;else
dbms_output.put_line('found的属性为'||c_sd%found);dbms_output.put_line('循环完毕,rowcount的属性为:'||c_sd%rowcount);exit;endif;endloop;
dbms_output.put_line('---------------------------------------------------------');closec_sd;
ifc_sd%isopenthen
dbms_output.put_line('执行close后,游标已关闭');else
dbms_output.put_line('执行close后,游标未关闭');endif;end;
~动态游标(无论是显示游标还是隐式游标,都具有一个特点,既游标打开时,其
定义类型,声明一个游标变量)
createorreplaceprocedurepri_sd(i_ageinnumber)asbegindeclare
typesd_typeisrecord(idnumber,namevarchar2(20),agenumber);
typest_typeisrefcursorreturnsd_type;stst_type;sdtsd_type;begin
ifi_age<=0then
openstforselect*fromsd;else
openstforselect*fromsdwhereage=i_age;endif;
fetchstintosdt;whilest%foundloop
dbms_output.put_line(sdt.id||':'||sdt.name||':'sdt.age);
fetchstintosdt;endloop;closest;end;endpri_sd;
||
ORACLE学习笔记
2.弱类型动态游标(编程语言有强弱之分,VB、JavaScript属于弱语言,Java、C
等属于强类型。弱类型动态游标在声明时不使用关键字return指定游标的返回类型,在以后的程序中可对其使用不同的返回类型。)
createorreplaceprocedurepri_st(i_flginvarchar)aswhilests%foundloop
dbms_output.put_line(age.id||'号学生的年龄是:'||age.age);
fetchstsbegindeclare
typename_typeisrecord(idnumber,
namevarchar2(20));typeage_typeisrecord(idnumber,agenumber);
typests_typeisrefcursor;namename_type;ageage_type;stssts_type;begin
ifupper(i_flg)='NAME'thenopenstsfor
selectid,namefromsd;fetchstsintoname;
whilests%foundloop
dbms_output.put_line(name.id||name.name);fetchstsintoname;endloop;
elsifupper(i_flg)='AGE'thenopenstsfor
selectid,agefromsd;fetchstsintoage;
号学生的名字是:'intoage;endloop;endif;
ifsts%isopenthenclosests;endif;end;endpri_st;
——当使用不同的参数时,可以为同一个游标使用不同的返回值类型,以实现灵活的功能
3.比较两种动态游标
强类型动态游标在使用时,必须声明其类型,在以后的使用过程中,虽然游标的定义可修改,但返回值的类型是一样的。而弱类型则无需声明返回值的类型,但在使用过程中,必须保证每次用于获取记录的类型能够正确接受来自游标的数据,因此存在一定风险,经量避免使用弱游标。
~cursorfor游标使用简单方便,值得关注—作用对象可以是任意复杂的查询语句
setserverouton;begin
forstin(select*fromsdwhereage>10andage<20orderbyage)loop
dbms_output.put_line(st.id||st.name||st.age);endloop;end;
触发器(数据库常用对象之一。主要部分是代码块,一旦创建,在条件成立时,代码块将自动执行;好处在于用户只需建立触发器,而无需对其进行任何人为控制,数据库将精确的完成触发器任务,实际上用户也不能显示的调用触发器。针对不同的动作和对象可以分为若干类)
~触发器简介(结构上类似于存储过程,为实现特殊功能而执行的代码块,不过触发器不允许显式的传递参数,不能返回参数值,也不允许用户调用触发器。触发
'||
户事件触发器,前三种针对于一般数据表,而系统和用户事件触发器则更侧重于针对数据库和用户操作触发,换言之,对数据表的insert、update、delete等DML操作应使用前三类触发器,除此之外,数据库的系统事件,例如数据库启动、关闭等一般使用数据库系统事件触发器,用户的drop、alter等DML操作一般使用用户事件触发器)
~创建和使用触发器
createtablet_em(idnumberconstraintpk_idprimarykey,namevarchar2(10),work_yearnumber,statusvarchar2(20));
createtablet_sa(s_idnumber,idnumberconstraintfk_pk_idreferencest_em(id),monthvarchar2(6),salarynumber);
1.创建触发器基本语法如下:
cteatetrigger[trigger_name]on[dbo].[table]forinsert,update,deleteas
sql_statement
演示如何利用触发器强制设置新进员工的服务年限为0:
createorreplacetriggertr_befor_insert_embeforeinsertont_emforeachrowbegin
:new.work_year:=0;end;
上述语句是一个完整的创建语法—描述触发器,定义触发器代码块;在触发器描述和代码块之间不能出现分号2.触发器的作用级别
foreachrow将触发器的作用级别定义为行级,也只有在此时的行级触发器才能使用:new变量,因此创建触发器时,应该特别注意其级别。
createorreplacetriggertr_befor_insert_embeforeinsertont_em
————ORA-04082:NEW或OLD引用不允许在表级触发器中
表触发器的常见应用场景并不在于限制数据,而是更多的应用于整个表的控制。
createorreplacetriggertr_befor_insert_embeforeinsertont_embegin
ifuser!='ADMIN'then
raise_application_error(-20001,'权限不足,不能向数据表插入数据');endif;end;
3.在多个事件上定义触发器(其实可以为多个事件同时定义触发器)
createorreplacetriggertr_insert_update_embeforeinsertorupdateont_emforeachrowbegin
:new.status:=upper(:new.status);end;
利用or连接多个事件并应用于触发器,oracle会同时监视数据表的这些事件,并分别调用触发器进行处理。
4.为同一事件定义多个触发器(可以为同一事件定义多个触发器,触发器的顺序
按照触发器的创建时间,排在较前位置的将首先触发)
5.触发器限制(触发器可以指定限制条件,以确定触发器是否应该触发)
createorreplacetriggertr_before_update_embeforeupdateont_emforeachrow
when(old.status='CXL'andold.work_year>0)begin
:new.status:='ACT';end;
ORACLE学习笔记
更新、查看:updatet_emsetid=id;select*fromt_em;
~语句触发器(指建立在表或视图上的、由表的特定操作触发的触发器,如insert、update、delete等。语句触发器是表级触发器,语句触发器只能被调用一次)
1.创建语句触发器(利用语句触发器实现一个常用的功能—记录表的修改日志,
记录修改日志以便追踪,是一个常见的功能需求)
createorreplacetriggertr_em_logbeforeinsertorupdateont_embegin
insertintoem_logvalues(user,sysdate);end;
查询:selectup_by,to_char(up_at,'yyyy-mm-dd')up_atfromem_log;
2.触发器谓词(对于触发器的动作,oracle提供了谓词,来判断触发动作的类型;
常用的谓语包括:inserting、updating、deleting,这些谓词都会返回一个布尔值,以表示激活动作是否为insert(插入)、update(更新)、deleting(删除)。当某个触发器被激活时,oracle会自动更新这三种谓语的值,需要注意的是,
3.触发时机(触发机制包括:before、after(实际操作之后),在使用before和after
之前,首先应该分析使用场景,权限应使用before,log应使用after这是因为插入、更新、删除等操作有可能返回错误,事务需要回滚,那么用户没有进行实
际操作,不必记录log)
createorreplacetriggertr_em_log
afterinsertorupdateordeleteont_embegin
ifinsertingthen
insertintoem_logvalues(user,sysdate,'插入数据');
endif;
ifupdatingthen
insertintoem_logvalues(user,sysdate,'更新数据');endif;
ifdeletingthen
insertintoem_logvalues(user,sysdate,'删除数据');endif;end;
4.触发器级联(指当某个事件激活了触发器时,该触发器的操作可能涉及另外一
个表,而针对涉及表的操作可能激活建立在该标识上的触发器。若该触发器的操作再次激活最初的触发器,将会造成死循环。触发器的级联往往会造成不可预知的问题)
~行触发器(行触发器在表的每行上进行操作时都会激活并执行一次代码,行触发器必须包含foreachrow子句,并且可以引用每行的数据,因此行触发器可以实现更加精细和强大的功能)
1.行触发器与引用(行触发器可以建立在insert操作之上,但此时触发器只能使
用:new引用,而不能用:old,因为insert操作并不存在旧的数据;但对于update操作,:new和:old都可以引用;delete操作只能使用:old引用)2.触发时机与引用(行触发器可以使用new和old引用,因此可以利用触发器记录
历史数据,无论是before还是after,都能使用old引用和new引用来获得每行数据更新前和更新后的状态)
3.触发时机与瞬态(瞬态是对指针表来说的,当表被修改时,其状态是瞬态的,
正是因为其不确定性,ooracle不允许访问一个瞬态表。在oracle的用户手册中描述了触发机制与瞬态的关系:当使用行触发器时,如果使用了before关键字,那么使用单条插入的方式可以访问触发器的关联表,如果使用了批量插入的方式,将不能访问触发器的关联表,因为此时的触发器关联表是瞬态的。beforeinert允许单条插入,不允许批量插入,因为在触发器访问一个表时,要求该表
ORACLE学习笔记
状态是确定的。对于beforeinsert是存在这种机会的,因为在插入数据之前,表的状态是确定的,所以使用单条插入的方式是可行的;但是对于批量插入的方式,由于触发器会被每行数据触发一次,每次都能改变数据表的实际数据,很难保证针对每次beforeinsert数据表的状态是确定的,因此oracle不允许批量插入的方式用于beforeinsert触发器)~insteadof触发器(语句触发器和行触发器与触发动作(如inserte、update、delete)之间是一种附属关系。触发器依赖于触发动作,但触发动作本身所执行的操作任然被执行。二者的效果是叠加起来作用于数据表的。而insteadof则是用于代替触发动作。例如insert动作的触发器则不是执行insert动作,而是转而执行触发器动作)1.创建和使用insteadof触发器(insteadof触发器提出是有必要的,因为对于某
些对象并不能进行直接的insert和update等动作,但有时又需要按照一定的逻辑来执行这些操作)创建视图统计合计工资:
createorreplaceviewvw_em_saas
selecte.id,e.name,sum(s.salary)astotalfromt_eme,t_saswheree.id=s.idgroupbye.id,e.name;
希望修改员工的实际工资,工资的差额按月均摊到salary列中(对视图vw_em_sa
直接进行update等操作是不行的,因为视图中没有任何一列对应于t_sa中的salary,可利用insteadof触发器来代替视图的update操作)创建insteadof触发器更新视图:
createorreplacetriggertr_up_em_sainsteadofupdateonvw_em_sabegindeclare
totalmonthnumber;begin
selectcount(distinct(month))intototalmonthfromt_sa
whereid=:old.id;updatet_sa
setsalary=salary+(:new.total-:old.total)/totalmonthwhereid=:old.id;end;end;
查询id=1的工资状况:
select*fromvw_em_sawhereid=1;
尝试修改工资总额:
updatevw_em_sasettotal=3000whereid=1;
查询:
select*fromvw_em_sawhereid=1;select*fromt_sawhereid=1;
——触发器对表的修改,仍然当作是对视图的修改看待
回滚操作:rollback—伴随视图的回滚操作,触发器的操作也一并回滚。
由于触发器的存在,经无法通过视图修改标的其他列,若欲对列进行处理,需将其加到触发器的处理语句中
2.Insteadof触发器与引用(可看作是行触发器,而不必引用foreachrow进行限
制,另外,insteadof虽然可以访问:new引用,但不能修改引用的值)
ORACLE学习笔记
~系统事件与用户事件触发器(是指oracle数据库本身的动作所触发的事件。包括:数据库启动、数据库关闭、系统错误等,用户事件是指相对于用户所执行的表(视图)等DML操作而言的,常见的用户事件包括:create事件、truncate事件、drop事件、alter事件、commit事件和rollback事件。系统事件和用户事件触发器并非常用触发器)
1.系统事件触发器(创建方法与其他触发器相同。事件创建after类型的触发器。数据库的startup事件没有before类型的触发器,这是因为触发器也是数据库的对象之一,在数据库启动之前,触发器是不能工作和捕捉事件的,同样,不能为shutdown事件创建after类型的触发器,因为数据库关闭之后,所有数据对象包括触发器都将无法使用。)
2.用户事件触发器(作用对象一般是user.schema,即将触发器建立在该用户及用户所拥有的所有对象之上)
createtabletmpasselect*fromt_em;
创建触发器:
createorreplacetriggertr_system_truncateaftertruncateonsystem.schemabegin
insertintotruncate_log
values(ora_dict_obj_name,ora_dict_obj_type,sysdate);end;
对表tmp进行操作:
truncatetabletmp;
查询
select*fromtmp;select*fromtruncate_log;
需要注意:对truncate_log进行操作,仍然会激发触发器使truncate_log有记录
~启用和禁用触发器(可使用alter命令修改触发器的属性)1.禁用和启用触发器的场景(启用和禁用触发器是必要的。一旦创建就默认有效,
那么相应的条件都会激活触发器,但要注意,触发器的执行会消耗大量的系统资源,尤其是针对数据表的行级触发器,例如大量数据插入时的beforeinsert触发器,,数据可认为无需经过触发器操作,如数据库迁移,可禁用触发器,当数据库插入完毕后再次启用触发器即可)2.禁用触发器(altertriggertrigger_namedisable)
createtableweek_day(week_dayvarchar2(10));
createorreplacetriggertr_insert_week_daybeforeinsertonweek_dayforeachrowbegin
:new.week_day:=upper(:new.week_day);end;
insertintoweek_dayvalues('monday');select*fromweek_day;→→→→大写
altertriggertr_insert_week_daydisable;
insertintoweek_dayvalues('tuesday');→→→→小写
3.启用触发器(altertriggertrigger_nameenable)
altertriggertr_insert_week_dayenable;→→→→大写
4.触发器信息(为获得当前的触发器信息可利用视图user_objects和user_triggers)selectobject_name,object_type,statusfromuser_objectswherelower(object_name)='tr_insert_week_day';
→→valid
select
trigger_name,trigger_type,triggering_event,table_name,statusfromuser_triggerswhere
lower(trigger_name)='tr_insert_week_day';
→→触发器的名称;触发器的类型:行级、before类型;触发器的触发事件