2. 常用数据字典用toad之类的工具直接可以浏览对象, 用到时再说3. SCN, select操作系统会分配一个SCN, 数据块也有一个SCN(也是在内存的cache中)无论是same session 还是 different session, 只要记住一点,你要 select 时,系统会分配一个SCN(SYSTEM CHANGE NUMBER),只能增加不能减少的一个NUMBER,每读一个数据块( 数据块本身也有SCN), 当自己的SCN 大于数据块的SCN,意味着,这个数据块没有被修改。反之,到 UNDO SEGMENT 里找到相应数据块,读取该信息。
4. index (结构, 优化)这里只介绍B*树索引, 最常用的一种索引, 这种索引, 一个索引条目就是对应一行B*树索引不存在非唯一条目, (索引也是一个存储结构, 在这个存储结构中不存在两行完全相同的数据),具体参考, blog->大师->11index
5. buffer cache 工作原理dirty buffer, free buffer, clean buffer(buffer内容与数据文件一致), pin buffern(当前正在更新的数据块)对于clean buffer, free buffer 统称为可用buffer.LRU 最近最少被使用的buffer链表, 先被使用的放在后边, 后被使用的放在前边, 如果Buffer被DML语句修改了,则该buffer会从LRU链表上摘下来, LRU链表上的buffer都是可用的数据块.当服务器进程无法找到空的buffer来存放新的数据请求时, 则需要把已经存放了数据的buffer拿来使用, 也就是用新的数据块内容覆盖曾经使用过的buffer, 在查找应该覆盖哪个buffer时, oracle会在LRU链表的尾部开始扫描, 如果扫描到的buffer正在被使用, 则跳过该buffer, 继续往下找, 直到找到为止, 如果扫描了一定量的buffer以后还没找到可用的buffer, 则说明脏数据块太多了, 于是触发DBWn进程, 将脏数据块刷新到数据文件里, 刷新完毕以后,buffer的内容与数据文件里的内容一致, 于是这些脏数据块变成了clean buffer, 就可以被覆盖了, 这些干净的buffer就会被挂在LRU链表尾部.数据库崩溃时, 重做日志文件的起点, 是哪?CKPT后台进程, 检查点进程, 这个进程与 DBWn合作, 从而确定这个重做的起点, 这个起点也有一个专门的名字, 叫做检查点位置(checkpoint position)该检查点位置记录在控制文件里, oracle为了在检查点的算法上更加的具有可扩展性,(也就是能够在巨大的buffer cache下依然有效工作), 引入了检查点队列(checkpoint queue), 该队列串起来的都是脏数据块所对应的 buffer header, 而每次DBWn写脏数据块时, 也是从检查点队列上扫描脏数据块, 并将这些脏数据块实际写入数据文件.当写完以后, DBWn 会将这些已经写入数据文件的脏数据块从检查点队列上摘下来, 这样即便在巨大的buffer cache下工作,CKPT也能狗快速的确定哪些脏数据块已经被写入了数据文件, 而那些还没有写入数据文件, 显然, 只要在检查点队列上的数据块都是还没有写入数据文件的脏数据块, 同时为了能够尽量减少实例崩溃后恢复的时间, oracle还引入了增量检查点, 从而增加了检查点的启动次数.6. Hints, Explain plan (autotrace, book: cost-based oracle fundamentals, )写hint的目的, 手工指定SQL语句的执行计划, 以下是常用的控制方式:1) 表的访问路径, 全表扫描, 索引扫描, 还是直接利用rowid/*+FULL(tablename)*/ /*+ROWID(tablename)*/ /*+CLUSTER(tablename)*/ /*+INDEX(table [index_name])*//*+NO_INDEX(TABLE [index_name])*/2) 表之间的连接类型/*+USE_NL(TABLE)*/ -- 嵌套 /*+USE_MERGE(TABLE)*/ /*+USE_HASH(TABLE)*/3) 表之间的连接顺序/*+ ORDERED*/ 按照from子句中标的顺序从左到友的连接/*+ STAR*/ 指优化器使用星型查询7. 绑定变量窥探绑定变量窥探的作用是在SQL语句硬分析的时候, 查看一下当前SQL谓词的值, 以便胜场最佳的执行计划.要注意的是,Bind Peeking只发生在硬分析的时候,即SQL被第一次执行的时候,之后的变量将不会在做peeking, 所以, 对调优来说, 意义不大.在10g 中绑定变量窥探有一个缺点,绑定变量窥探不管后续传入的绑定变量的具体输入值是什么,它会一直沿用之前第一次硬解析时所产省的解析树和执行计划(这个缺点在oracle 11g中引入自适应游标共享后才得到了改善)。因为它可能使CBO在某些情况下所选择的执行计划并不是目标SQL在当前情况下的最优执行计划,而且它可能会带来目标SQL执行计划的突然改变,影响系统的性能。注意: 绑定变量窥探表明, 有时候执行SQL时, 不使用绑定变量比使用绑定变量还好, 但是在11G以后, 由于绑定变量得到改善, 所以, 还是推荐使用.8. 物化视图, 需要刷新来进行同步基本表, 在OLAP中使用较多
9. 调优SQL基本原则a. 书写格式要规范, 比如大小写b. 使用绑定变量c. 是否使用索引: 只有嵌套连接会使用到索引, 其他连接, 索引没有什么实际意义d. 看连接的顺序是否能使用到索引e. 数据字典或视图, 是否被分析过f. 索引列是否函数参数, 注意, 函数对索引的影响g. 是否存在潜在的数据类型转换, 从而导致索引跟函数有关, 例如字符型转换为数值型, 那么oracle会自动调用to_number()函数h. 带通配符(%)的 like 语句如果通配符(%)在搜寻词首出现,oracle 系统不会使用索引。 在很多情况下可能无法避免这种情况,然而当通配符出现在字符串其他位置时,优化器就能利用索引。 在下面的查询中索引得到了使用:select * from user_m where loginid like ‘r%‘;10.查看oracle文档, 参考blog->oracle实验->如何查看oracle文档
11.oracle 在多表连接时, 一定会两个两个进行连接, 一共有4种连接方式, 嵌套连接, 笛卡儿积, 归并连接, hash连接嵌套连接: 主要连接方式, 读取都会利用到索引, 首先读取主表的一个值, 在附表中根据该值读取索引, 通过索引读取附表中对应的行, 进行连接. 类似 for 循环, 主表是外层, 内层是附表归并连接: 先将两个表分别排序, 然后再对已经排序的的两个表进行join(注意, 这个join不同于嵌套连接, 可以想数据结构中的归并排序) 通常, 归并连接在非相等连接操作中有用.散列连接: 全扫描一个小表, 然后对这个小表的值, 做散列(即hash函数), 然后再全扫描较大的表, 针对值进行映射 通常, 散列擅长一个大一个小的两个表之间的join.笛卡儿积: 最普通的连接, 全连接注意: 只有嵌套连接会使用到索引, 其他连接, 索引没有什么实际意义在返回结果集大于 1 W 行时, 不建议使用嵌套循环连接, 应考虑使用hash连接或排序合并连接进行替换. 说明: 返回大量结果集时嵌套循环连接成本较高, 效率很低, 此时应考虑变换连接方式, 特别在使用RBO优化器时, 嵌套循环连接的优先级较高, 通常需要用 “提示” 来强制改变连接方式.两个无序大表的连接, 在连接字段无索引时, 不建议使用合并排序连接 说明: 排序合并联结需要先对两个表按连接字段进行排序, 如果两个表都非常大, 其排序操作的代价会非常巨大.在建立复合索引时, 尽量把最常用的字段放在最前面, 尽量把离散值较少的字段放在前面, 尽量保证复合索引中至少有一个字段具有非空约束.12.访问数据的方式首先介绍访问数据的几种方法: 全表扫描, 通过制定rowid来访问, 索引扫描, 下面主要介绍一下索引扫描B*树结构 : 该书中的最低级的块(成为叶子结点)包含了每个索引键值和一个指向正在索引的行的 ROWID(换句话说, 通过索引键值, 找到ROWID, 在通过ROWID去找真正的行), 有趣的是, 索引的叶子结点实际上是一个双向链表, 这样, 要执行区间扫描就很容易, 直接找这个结点的前边或者后边就可以了.索引扫描又分为很多种: 主要介绍两种:索引唯一扫描, 索引范围扫描索引唯一扫描: 优化程序知道索引中索引列是唯一的, 从索引查找中至多返回一行.索引范围扫描: 对于索引范围扫描, 优化器知道可能返回 0行, 1行或多行. 例如 select max(empno) from emp; 这个查询, oracle 不是将全表扫描一遍然后查出最大的, 而是直接通过索引的后面开始读取最后(最高)的值. (因为一般情况下索引是按照从低到高存储的).13.锁相关问题:有可能产生丢失更新, 解决的办法是, 只改变你确实想改变的列, 而不是将所有列都改变锁的策略: 个人推荐乐观锁定, 并且是要求数据库所有的用户都使用乐观锁可以通过增加一列timestamp来判断你更新的这行是否没有被别人更新过.注意这里的条件, 包括了 timestamp, 所以如果在之前有人修改过这个table, 那么本地保存的timestamp数据就是"旧数据", 而此时如果你保存的是旧数据的话, 那么更新将不能进行, 因为条件不满足, 可以通过将所有的update语句封装在procedure中, 从而让procedure来判断每次更新, 这主要是为了防止某些程序员在更新时忘记更新这个时间戳, 详情参考 blog->大师->06Locking and Latching阻塞&死锁: 当你所要申请的资源被占用了, 那么你就被自锁了. 死锁: 互相申请的资源都被阻塞了, 就死锁了死锁的处理办法, 一般是人为干预, "回滚"一个, 释放资源. 出现死锁的最可能原因是外键没加索引.
锁类型TX锁, 事务发起第一个修改时会得到TX锁(事务锁), 而且会一直持有这个锁, 直至事务执行提交(commit)或回滚(rollback)TX锁用作一种排队机制, 使其他回话可以等待这个事务执行.事务中修改或通过select for update 选择的每一行都会"指向"该事务的一个相关TX锁, 听上去好像开销很大, 但实际并非如此, 要想知道为什么, 需要从概念上对锁"居住" 在哪里以及如何管理有所认识, 在oracle中,闩为数据的一个属性, oracle并没有一个传统的锁管理器, 不会用锁管理器为系统中锁定的每一行oracle锁定的过程:1) 找到想锁定的那一行地址.2) 到达那一行3) 锁定这一行(如果这一行已经锁定, 则等待锁住它的事务结束, 除非使用了 nowait 选项)这里体现了TX锁的排队机制说明: 闩是数据的一个属性, 事务找到数据, 如果还没有被锁定, 则对其锁定, 在oracle对数据进行锁定时, 行指向事务ID的一个副本, 事务ID存储在包含数据的块中, 释放锁时, 事务ID会保留下来, 这个事务ID是事务所独有的, 表示了撤销段号, 槽和序列号, 事务ID是说明"这个事务ID 你"拥有这个数据(并非数据块上所有的数据都是你的, 只是你修改的那一行"归你"),另一个session来到时, 它会看到锁ID, 由于锁ID表示一个事务, 所以可以很快的查看持有这个锁的事务是否还是活动的, 如果锁不活动, 则准许会话访问这个数据. 如果锁还是活动的, 会话就会要求一旦释放锁就得到通知.补充: 所有的闩latch是一种轻量级锁, 用来控制争用资源的, 有点类似令牌, 你想做什么时, 先得到令牌才能做, 做完以后, 归还令牌,别人才能做. 另外, 闩会自旋.update操作过程:假设 A 用户发出一条 update 语句: update employees set last_name = ‘HanSijie‘ where employee_id = 100;oracle 在对该SQL进行解析后, 找到 employee_id 为100的记录所在的数据块(假设为58号数据块), 并找到一个可用的undo 数据块,将 last_name 列上被更新前的旧值放入该 undo 数据块, 然后在数据块头部分配一个 ITL 槽, 在该ITL槽里存放当前事务ID号, SCN号, 所使用的undo数据块的地址, 以及当前还未提交的标记等信息, 接下来, 在58号数据块中, 找到被更新的数据行, 在其头部设置一个锁定标记, 并在头部记录当前事务所使用的ITL槽的曹号. 做完这些工作后, 将控制权(也就是光标)返回给用户. 该锁定标记说明当前用户在被修改的数据行上已经添加了X锁.
如果这时, 另一个用户(假设为B)也对 employee_id 为 100的记录进行修改, 则其过程和上面描述的一样, 只不过B在对数据行的头部设置锁定标记时, 发现该数据行头部已经有一个锁定标记了, 说明记录已经被添加了X锁, 于是用户进程B必须等待, 等待该锁被释放.对应存储结构中的 INITRANS 和 MAXTRANS在创建table的storage语句时, 会有 INITRANS 和 MAXTRANS 两个参数, 这里对应上了, 就是说事务槽的个数, oracle10g后这个参数被废除,但是, 最起码我们对大致的脉络有了一个清晰的认识.以上都是说的 TX型锁, 下边说说其他类型的锁:TM锁: 作用, 比如你修改了一个表, 就会得到这个表的TM锁, 这是时候如果有人想drop这个表, 需要先获得TM锁DDL锁: DDL操作时, 会得到DDL锁, 目的是, 在你修改对象时14. redo 与 undo 的合作回滚时, undo 做的是逻辑上与redo相反的是, 比如, 原来是insert操作, 那么回滚时, 就是delete操作比如一条insert语句, 那么, redo做的是让这个语句再次发生, 而undo做的是让这个insert语句消失另外, redo 同样保护 undo, 就把undo想象成普通的表空间就可以了.详细参考 blog->大师->09->redo和undo如何合作专题
15.autotrace 比较看重的几个点recursive calls: 递归调用, 有可能是由硬解析造成的所需要的数据库=dblocks gets(在data buffer中的读取) + cosistent gets(在undo buffer中读取)phsical reads: I/Oredo size: 产生了多少重做日志执行计划的读法: 对同一凹层, 先上后下执行, 对不同凹层, 先里后外执行.16. logswitch 触发的是 增量检查点, (只针对要覆盖的那个日志文件的内容来进行DBWn的操作), 从而可以推断,在检查点队列上串起来的脏数据, 是根据数据库的改变顺序来的, 即日志文件的顺序.
17. 需要调优的SQL运行时间长的SQL逻辑读高的SQL物理读高的SQL
ORACLE 总结
标签:
小编还为您整理了以下内容,可能对您也有帮助:
oracle 11g错误代码20怎么解决
在$ORACLE_HOME/NETWORK/ADMIN目录下,存放着*的配置文件,其中,那个叫做SAMPLE的文件夹是*配置的举例,虽然是英文,但花点时间的话还是能基本看懂的。回到正题,SAMPLE文件夹旁边还有两个扩展名为.ora的文件,可以用记事本之类的软件打开。里面存放着*的各种配置。
回到这个故障的话题,网上看到一个方法,说是主机名可能设置的不对,就是那两个.ora文件中的HOST选项,于是查看了一下详细情况:
listener.ora文件中HOST的值为180.111.140.106,看上去是个*地址;
tnsnames.ora文件中的HOST值为localhost,很显然是本机地址;
既然这两个HOST值不一样,那估计问题就出在这了,因为要连接的是本机上的数据库,所以就把两个HOST的值都改成127.0.0.1,然后找到Windows服务中的OracleDb11g_homeTNSListener这条,先停止它,然后再启动。如下图:
然后回到SQL Developer,重新连接数据库,OK~
oracle 11g错误代码20怎么解决
在$ORACLE_HOME/NETWORK/ADMIN目录下,存放着*的配置文件,其中,那个叫做SAMPLE的文件夹是*配置的举例,虽然是英文,但花点时间的话还是能基本看懂的。回到正题,SAMPLE文件夹旁边还有两个扩展名为.ora的文件,可以用记事本之类的软件打开。里面存放着*的各种配置。
回到这个故障的话题,网上看到一个方法,说是主机名可能设置的不对,就是那两个.ora文件中的HOST选项,于是查看了一下详细情况:
listener.ora文件中HOST的值为180.111.140.106,看上去是个*地址;
tnsnames.ora文件中的HOST值为localhost,很显然是本机地址;
既然这两个HOST值不一样,那估计问题就出在这了,因为要连接的是本机上的数据库,所以就把两个HOST的值都改成127.0.0.1,然后找到Windows服务中的OracleDb11g_homeTNSListener这条,先停止它,然后再启动。如下图:
然后回到SQL Developer,重新连接数据库,OK~
oracle触发器使用总结
触发器 是特定事件出现的时候,自动执行的代码块。类似于存储过程,但是用户不能直接调用他们。触发器是许多关系数据库系统都提供的一项技术。在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块。
1.说明
1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用
2)触发器分类:
1.DML触发器: 创建在表上,由DML事件引发
2.instead of触发器: 创建在视图上并且只能在行级上触发,用于替代insert,delete等操作(由于oracle中不能直接对有两个以上的表建立的视图进行DML操作,所以给出替代触发器,它是专门为进行视图操作的一种处理方法)
3.DDL触发器: 触发事件时数据库对象的创建和修改
4.数据库事件触发器:定义在数据库或者模式上,由数据库事件触发
3)组成:
1.触发事件:引发触发器被触发的事件 DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件
(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。
2.触发时间:即该触发器是在触发事件发生之前(BEFORE)还是之后(AFTER)触发
3.触发操作:触发器触发后要完成的事情
4.触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,触发器才会执行触发操作。
5.触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发操作。
6.触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。(比如delete多条数据时,行级触发器可能会执行多次,语句级触发器只会触发一次)
2.语法
1)说明
不同类型的触发器例如DML触发器,Instead of触发器,系统触发器语法格式区别较大
2)一般语法
CREATE [OR REPLACE] TIGGER触发器名 触发时间 触发事件ON表名/视图名[FOR EACH ROW] //加上FOR EACH ROW 即为行级触发器,不加时为语句级触发器BEGINpl/sql语句END
create [or replace] trigger [schema.]trigger_name {before | after | instead of} {delete [or insert][or update [of column,...n]]} on [schema.]table_name | view_name [for each row [when(condition)]] sql_statement[,...n]
例如:
CREATE OR REPLACE TRIGGER trigger_name before | after | instead of insert | update | delete ON table_name[FOR EACH ROW]WHEN (condition)DECLAREBEGINEND;
3)instead of 触发器语法
语法:
CREATE [OR REPLACE] TRIGGER trigger_name INSTEAD OF{INSERT|DELETE|UPDATE [OF COLUMN...]}[OR {INSERT| DELETE| UPDATE [OF COLUMN...]}]ON VIEW_NAME[REFFERENCING{OLD [AS] OLD | NEW [AS] NEW| PARENT AS PARENT}] // 可以指定相关名称,当前的默认相关名称为OLD和NEW,应用相关名称时需要加:[FOR EACH ROW] //instead of 触发器只能在行级上触发,因为没有必要指定[WHEN CONDITION]DECLAREBEGINEND;
说明:INSTEAD OF 用于对视图的DML触发,由于视图可能有多个表进行联结而成,因而并非所有的联结均可更新,运用 INSTEAD OF 触发器可完成相应的操作。
3.实例
创建测试表格:
CREATE TABLE "HNZC"."TRIGGERTEST" ( "ID" VARCHAR2(20 BYTE), "NAME" VARCHAR2(20 BYTE), "SCORE" NUMBER );create table tab1 select * from triggertest;
1)DML触发器/行级触发器
触发器如下:
CREATE OR REPLACE TRIGGER TRIGGER1 AFTER INSERT ON TRIGGERTEST //插入后触发FOR EACH ROW //行级触发器BEGIN INSERT INTO tab1(ID,NAME) VALUES('22','33');END;
执行语句:
insert into triggertest (id) values ('aabbcc');
语句执行结束,表tab1中新增加一条数据
2)对表的修改(例如非工作时间不能修改某些表)
触发器如下:
CREATE OR REPLACE TRIGGER TRIGGER1 AFTER INSERT ON TRIGGERTEST FOR EACH ROW BEGIN IF(TO_CHAR(SYSDATE,'DAY') IN ('星期三','星期天')) THEN RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不能修改表格triggertest'); END IF;END;
执行语句:
insert into triggertest (id) values ('aabbcc');
今天周三因而输出结果为:
在行 1 上开始执行命令时出错:insert into triggertest (id) values ('aabbcc')错误报告:SQL 错误: ORA-20001: 不是上班时间,不能修改表格triggertestORA-06512: 在 "HNZC.TRIGGER1", line 3ORA-04088: 触发器 'HNZC.TRIGGER1' 执行过程中出错
通常对表的修改如下(即周一至周五9——18点能修改表格)
CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW BEGIN IF(TO_CHAR(SYSDATE,'DAY') IN ('星期六','星期天')) OR(TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '9:00' AND '18:00') THEN RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不能修改表格triggertest'); END IF;END;
3)增加条件(如不能更改某个员工的记录)
触发器如下:(如下实现月儿的分数只能增加)
CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW WHEN(OLD.NAME='月儿')BEGIN CASE WHEN UPDATING('SCORE') THEN IF:NEW.SCORE:OLD.SCORE THEN RAISE_APPLICATION_ERROR(-20001,'月儿的分数只能提升不能下降'); END IF; END CASE;END;
当前月儿的分数为20
当修改为10时出错
UPDATE "HNZC"."TRIGGERTEST" SET SCORE = '10' WHERE ROWID = 'AAAdEzAAPAAAAH+AAB' AND ORA_ROWSCN = '47685303'ORA-20001: 月儿的分数只能提升不能下降ORA-06512: 在 "HNZC.TRIGGER1", line 4ORA-04088: 触发器 'HNZC.TRIGGER1' 执行过程中出错
当修改为30时成功
UPDATE "HNZC"."TRIGGERTEST" SET SCORE = '30' WHERE ROWID = 'AAAdEzAAPAAAAH+AAB' AND ORA_ROWSCN = '47685303'提交成功
4)在触发器中调用存储过程
触发器为:
CREATE OR REPLACE TRIGGER TRIGGER1 BEFORE INSERT OR DELETE OR UPDATE ON TRIGGERTEST FOR EACH ROW BEGIN TESTPRO1();END;
存储过程为:
create or replacePROCEDURE TESTPRO1 AS BEGIN insert into tab1(id,name,score) VALUES('AAA','BBB',200);END TESTPRO1;
执行完毕后tab1中增加一条数据
5)级联更新
触发器如下(triggertest表中name修改时同时修改tab1中的name)
create or replacePROCEDURE TESTPRO1 AS BEGIN insert into tab1(id,name,score) VALUES('AAA','BBB',200);END TESTPRO1;
执行语句:
update triggertest set name= '水儿' where name='月儿';
结果:tab1中name为月儿的也更改为水儿
6)instead of触发器
TABLE STUDENT表格数据如下
创建视图student_view
CREATE OR REPLACE VIEW STUDNET_VIEW AS SELECT CLASSID,AVG(SCORE) AVERAGE_SCORE FROM STUDENTGROUP BY CLASSID;
视图数据如下:
对视图student_view 执行如下操作:
DELETE FROM STUDNET_VIEW WHERE CLASSID='111';
执行结果:
错误报告:SQL 错误: ORA-01732: 此视图的数据操纵操作非法01732. 00000 - "data manipulation operation not legal on this view"
解决方法:创建INSTEAD OF 视图
CREATE OR REPLACE TRIGGER STUDENT_VIEW_DELETE INSTEAD OF DELETE ON STUDNET_VIEW FOR EACH ROWBEGIN DELETE FROM STUDENT WHERE CLASSID=:OLD.CLASSID;END STUDENT_VIEW_DELETE;
执行删除语句
DELETE FROM STUDNET_VIEW WHERE CLASSID='111';
执行结果:删除成功
1 行已删除。
4.注意事项
1) 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)
2) 触发器中不能使用commit语句,触发器的操作与触发事件(INSERT,UPDATE,DELETE)一起进行COMMIT和ROLLBACK;
3) 一个表上的触发器越多,对于表的DML操作性能影响越大
4) 触发器最大为32K
oracle 如何取表中所有数据的20%
select t.*,t.rid from (select * ,rownum as rid from table) t
where rid<= (select round(count(*)*0.2) as count from table);