庆祝s

或多或少
整理的Oracle精辟问答题(8)
1.触发器和过程有什么区别?
触发器与过程的区别在于:
过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的。
---------------------------------------------------------------------------
2.写一遍创建触发器的代码。
create or replace trigger 触发器名称
[before 在执行前|after 在执行后|instead of 关于视图操作]
{insert | delete | update}
on 表名 或者 视图名
【referencing 指定新行或旧行】
【for each row 行级锁或是表级锁】
---------------------------------------------------------------------------
3.有表forum(id number(9,0),title,content,author,fjs number(8,0),pubdate)
    表fj(id number,fid number(9,0),title,content,author,pubdate)
  请写存储过程当向表fj插入数据成功后,修改forum表中与fid对应的id行的fjs=fjs+1.
--建表
create table forum(id number(9,0),title varchar2(50),content varchar2(200),author varchar2(80),fjs number(8,0),pubdate date);
create table fj(id number,fid number(9,0),title varchar2(50),content varchar2(200),author varchar2(80),pubdate date);
--插入数据
insert into forum values(1,'测试','我的测试触发器','Peter',19,sysdate);
insert into fj values(1,1,'回复测试','回答 我的触发器','Lisa',sysdate);
--查询
select * from forum ;
select * from fj;
--建立触发器
create or replace trigger trigger_test
 after insert
  on fj
   referencing new as n
    for each row
     
begin
      if inserting then
       dbms_output.put_line(:n.ID);
       update forum set fjs=fjs+1 where id = :n.ID;
      end if;
   end;
   
---------------------------------------------------------------------------
4.instead of在创建存储过程是什么意思?
instead of 触发器是在视图上而不是在表上定义的触发器,它是用来替换所使用实际语句的触发器。
---------------------------------------------------------------------------
5.new 和old分别 是什么意思?
指定新行(即将更新)和旧行(更新前)的其他名称。
---------------------------------------------------------------------------
6.referencing是什么意思?for each row呢?
for each row
指定是否对受影响的每行都执行触发器,行几触发器,如果不用此子句,则为语句级触发器。

---------------------------------------------------------------------------
7.有表account(acct varchar2(20),acctname varchar2(50),bal number(9,2),flag varchar2(1))
  分别表示帐号,户名,余额,性质(0存储,1贷款)
  规则:存款户开户时必须交款10元(如一卡通)
  为了防止操作员在开户时填错余额,现要求写一存储过程来防止上述问题。
--建表
create table account(acct varchar2(20),acctname varchar2(50),bal number(9,2),flag varchar2(1));
--建立是否是新用户的过程过程
create or replace procedure proc_getnum(accout varchar2,accountname varchar2,num varchar2,numflag out number) is
 begin
  select count(*) into numflag  from account where acct=accout and acctname = accountname and flag = num;
 end;
--建立是否交款10元的过程
create or replace procedure proc_num(accout varchar2,accountname varchar2,bal number,flag varchar2) is
 num number;
begin
 proc_getnum(accout,accountname,flag,num);
 if num = 0 and bal < 10 then
  dbms_output.put_line('必须交款十元!');
 end if;
end;
--测试过程
begin
proc_num('1001','aaa',0.6,'1');
end;
--查询表
select * from account
------------------------------------------------------------------------------------
8.行级触发器指的是?如何定义行级触发器呢?
行级触发器对DML语句影响的每个行执行一次。
for each row;
------------------------------------------
9.有表ls(id number(9,0),acct varchar2(20),amount number(9,2),flag varchar2(1))
  其中字段Id是一个自动增长的字段,并已为其建立了序列seq_id,
  但程序员在为此表插入数据时并未为此字段指定值,
  请问我应如何做,才能让id按照序列值插入?
--建表
create table ls(id number(9,0),acct varchar2(20),amount number(9,2),flag varchar2(1));
--建立序列
create sequence seq_test;
---建触发器
create or replace trigger trig_test
 before insert
 on ls
 for each row
 begin
  if inserting then
   select seq_test.nextval into :new.ID from dual;
  end if;
 end;
--插入数据
insert into ls(ACCT,amount,FLAG) values ('aaa',93.02,'1');
insert into ls(ACCT,amount,FLAG) values ('bbb',152.36,'1');
insert into ls(ACCT,amount,FLAG) values ('ccc',23.65,'1');
insert into ls(ACCT,amount,FLAG) values ('ddd',45.89,'1');
insert into ls(ACCT,amount,FLAG) values ('eee',78.95,'1');
--查询数据
select * from ls

------------------------------------------
10.语句级触发器指的是?主要用来实现什么?
语句级触发器对每个DML语句执行一次
------------------------------------------
11.有表student(classid,stuid,stuname,stuaddress)班号,学号,学生姓名,学生地址
     表stumark(classid,stuid,clsid,mark)班号,学号,科目号,成绩
   其中表stumark的stuid与表stuid相对应,classid也与student表的classid相对应。有外键联系。
   现要求当删除student表中某班学生或某个学生时,先删除stumark中此班的所有或指定学生信息。
   请编写触发器来实现约束检查。
--删除表
drop table stumark;
drop table student;
--建表
create table student(classid varchar2(20),stuid varchar2(20) primary key,stuname varchar2(20),stuaddress varchar2(50));
create table stumark(classid varchar2(20),stuid varchar2(20),clsid varchar2(20),mark varchar2(20));
--建约束
alter table stumark add constraint Fk_mark Foreign Key(stuid) references student(stuid);
--建触发器
create or replace trigger trig_delinfoforstumark
 before delete
 on student
 referencing old as o
 for each row
 begin
  if deleting then
   dbms_output.put_line(:o.STUID);
   delete from stumark where stuid = :o.STUID;
  end if;
 end;
 
select * from student;
select * from stumark;

--插入数据
insert into student values ('A001','001','Peter','秦皇岛');

insert into stumark values('A001','001','SQL','100');
insert into stumark values('A001','001','JAVA','89.25');
--删除测试之

delete from student where stuid = '001';
 
------------------------------------------
12.我们知道要在视图上执行插入,删除更新记录时需要有键保留表的限制。如果不存在此限制时,如何才能删除视图数据呢?


利用触发器 Instead Of
------------------------------------------
13.以题11中的表为例,建立视图
   create view v_stu as select a.classid,a.stuid,a.stuname,b.clsid,b.mark from student a ,stumark b where a.classid=b.classid and a.stuid=b.stuid
   现在要通过删除视图来实现
   delete from v_stu where classid='....' and stuid='.....'
   请问应如何写触发器来实现。
--建立触发器  
 create or replace trigger trig_forview
    instead of delete on v_stu
    referencing old as o
    for each row
    begin
     delete from stumark where stuid = :o.STUID and classid = :o.classid;
     delete from student where stuid = :o.stuid and classid = :o.classid;
    end;
--测试DEL语句
   delete from v_stu where classid = 'A001' and stuid = '001'
   ---------/"/"/"/"/"/"/"/"/"/"/"/"/"---------
   现在要通过向视图插入数据来实现
   inset into v_stu values('0123','ts287','china','.net',88)
   请问应如何写触发器来实现?
--建立触发器   
    create or replace trigger trig_forview
    instead of insert on v_stu
    referencing new as n
    for each row
    begin
      insert into student(classid,stuid,stuname) values(:n.CLASSID,:n.STUID,:n.STUNAME);
      insert into stumark values (:n.CLASSID,:n.STUID,:n.CLSID,:n.MARK);
    end;
--测试Insert语句
   insert into v_stu values('0123','ts287','china','.net',88);
     
    select * from student;
    select * from stumark;
    select * from v_stu;
    
    select * from user_updatable_columns where TABLE_Name = 'V_STU'
------------------------------------------
14.模式触发器指的是?
如 create alter drop grant revoke 和 truncate 等DDL语句。用户可以创建触发器来防止删除自己创建的表。
模式触发器提供的主要功能是阻止DDL操作以及在发生DDL操作时提供额外的安全监控。
------------------------------------------
15.请写一触发器来记录本模式下对象创建的信息,保存内容包括(对象名,对象类型,创建日期)。
   触发器名称为newobj
   信息保存表为objdata(name varchar2(30),objtype varchar2(20),creatdate date)
  --建表
   create table objdata(name varchar2(30),objtype varchar2(20),creatdate date)
  --建触发器
   create or replace trigger trig_fortable
   after create on schema
   begin
    insert into objdata values(ora_dict_obj_name,ora_dict_obj_type,sysdate);
   end;
   --测试语句
   create table test(aa varchar2(20),bb varchar(30));
   select * from objdata
   create view view_tt
   as select * from test
 
   --查询objdata
   select * from objdata
------------------------------------------
17.数据库触发器指的是?
   --
   可以创建在数据库事件上的触发器,包括启动,关闭,服务器错误,登录和注销等。
------------------------------------------
18.如何禁用触发器newobj?
 alter trigger newobj enable;
 alter trigger newobj disable;
------------------------------------------
19.触发器保存在哪个数据字典中?

user_triggers
------------------------------------------
20.dbms_output包中的put,put_line,new_line分别是什么意思?
put--------把文本放到缓冲区里去
put_line---把缓冲区文本打印出来
new_line---用于向缓冲区中添加换行符。
------------------------------------------
21.dbms_lob包中的read,write和substr分别是什么意思?
read----此过程从LOB数据中读取指定长度数据到缓冲区。
write---此过程用于将指定数量的数据写入LOB.
substr---此函数从LOB数据中取子串
------------------------------------------
22.调用哪个包的哪个函数可以将查询结果转换为xml格式?它的返回值是什么类型?
   请写代码将student表中的数据转换为xml格式,并调用put_line显示出来?
   Dbms_Xmlquery包
   它的返回值是个CLOB类型
   
   select * from student
   declare
    results clob;
    xmlstr varchar2(32767);
    line varchar(2000);
    line_no integer := 1;
    begin
     results := dbms_xmlquery.getxml('select * from student');
     xmlstr := dbms_lob.substr(results,32767);
     loop
      exit when xmlstr is null;
      line := substr(xmlstr,1,instr(xmlstr,chr(10))-1);
      dbms_output.put_line(line_no || ':'|| line);
      xmlstr := substr(xmlstr,instr(xmlstr,chr(10))+1);--截取每一行一直到换行时的字符串  chr(10)是代表换行的ASCII码 instr('字符窜','要在该字符窜查找的字符')->返回一个数字
      line_no := line_no + 1;
     end loop;
    end;
select chr(36) from dual    
select instr('ssdf','s') from dual
------------------------------------------
23.如何来生成随机数与随机字符串?
--生成随机数
declare
 num number;
 begin
  num := abs(dbms_random.random  mod 100) ;
  dbms_output.put_line(num);
 end;
--生成随机字符串
declare
 num varchar2(100);
 begin
  num := dbms_random.string('A',1);
  dbms_output.put_line(num);
 end;
------------------------------------------
24.请写过程来将表中数据读取到的xml内容写到c:"mydata"mystudent.xml文件中。
--建立一个表
drop table roster;
create table roster
 (
  sid varchar2(20),
  sname varchar2(50),
  ssex varchar2(50),
  sdob varchar2(50),
  smark varchar2(50),
  ssub varchar2(50)
 )
--插入测试数据
 insert into roster values ('101','李华','男','1978.9.12','92','Java')
--建立一个过程
create or replace procedure proc_xmltotable(dir varchar,filename varchar2,errfile varchar2) is
p xmlparser.Parser;--建立一个解析器
doc xmldom.DOMDocument; --为读取XML文档
--在里面又定义了一个存储过程 需要xmldom.DOMDocument做参数
procedure readElement(doc xmldom.DOMDocument) is
 dnl xmldom.DOMNodeList;
 length number;
 strsql varchar2(2000);
 n xmldom.DOMNode;
 m xmldom.DOMNode;
 aname xmldom.DOMNamedNodeMap;--属性名
 length1 number;
 dnl1 xmldom.DOMNodeList;--读取student的子节点
 begin
  dnl := xmldom.getElementsByTagName(doc,'student');
  length := xmldom.getLength(dnl);
  for i in 0..length-1
   loop
    strsql := 'insert into roster values (';--
    dbms_output.put_line(strsql||'1');
    
    n := xmldom.item(dnl,i);
    if xmldom.getNodeName(n)='student' then
      aname := xmldom.getAttributes(n);
      m := xmldom.item(aname,0);
      strsql := strsql ||''''||xmldom.getNodeValue(m)||'''';
   
      dbms_output.put_line(strsql||'2');--
     end if;
     dnl1 := xmldom.getChildNodes(n);
     length1 := xmldom.getLength(dnl1);
     for j in 0.. length1-1
      loop
       n := xmldom.item(dnl1,j);
       strsql := strsql || ','''||xmldom.getNodeValue(xmldom.getfirstchild(n))||'''';--
       dbms_output.put_line(strsql||'3');
      end loop;
      strsql := strsql || ')';
      dbms_output.put_line(strsql||'4');
      execute immediate(strsql);
   end loop;
   commit;

 end readElement;
 begin
  p := xmlparser.newParser;--实例话
  xmlparser.setValidationMode(p,False);--设定解析器的状态
  xmlparser.setErrorLog(p,dir||'"'||errfile);--错误日志文件
  xmlparser.setBaseDir(p,dir);--目录
  xmlparser.parse(p,dir||'"'||filename);--设定文件的目录和文件
  doc := xmlparser.getDocument(p);
  readELement(doc);
  xmldom.freeDocument(doc);
  exception
  when xmldom.INDEX_SIZE_ERR then
     raise_application_error(-20120, 'Index Size error');
  when xmldom.DOMSTRING_SIZE_ERR then
     raise_application_error(-20120, 'String Size error');
  when xmldom.HIERARCHY_REQUEST_ERR then
     raise_application_error(-20120, 'Hierarchy request error');
  when xmldom.WRONG_DOCUMENT_ERR then
     raise_application_error(-20120, 'Wrong doc error');
  when xmldom.INVALID_CHARACTER_ERR then
     raise_application_error(-20120, 'Invalid Char error');
  when xmldom.NO_DATA_ALLOWED_ERR then
     raise_application_error(-20120, 'Nod data allowed error');
  when xmldom.NO_MODIFICATION_ALLOWED_ERR then
     raise_application_error(-20120, 'No mod allowed error');
  when xmldom.NOT_FOUND_ERR then
     raise_application_error(-20120, 'Not found error');
  when xmldom.NOT_SUPPORTED_ERR then
     raise_application_error(-20120, 'Not supported error');
  when xmldom.INUSE_ATTRIBUTE_ERR then
     raise_application_error(-20120, 'In use attr error');
 end porcxmltotable;
--执行过程
begin
 proc_tabletoxml('c:\mydata\','mystudent.xml','err.log');
end;
25.请写过程读取c:"mydata"mystudent.xml文件的内容并显示出来。
--建立过程
create or replace procedure proc_tableToXml(filename varchar2)
  is
   doc xmldom.DOMDocument; --定义全局XML文档的DOC
   mainnode xmldom.DOMNode; --根元素的标签对象
   rootele xmldom.DOMElement; --根元素的标签
   rootnode xmldom.DOMNode;   --根元素的标签的内容
   brachele xmldom.DOMElement; --叶元素的标签
   brachtext xmldom.DOMText;   --叶元素的标签的内容
   brachnode xmldom.DOMNode;   --叶元素的标签的对象
   student_node xmldom.DOMNode;--给根元素的标签确定为《student》
   cursor getinfo is select * from roster; --定义一个游标来查询表
  begin
   doc := xmldom.newDOMDocument; --初始化
   mainnode := xmldom.makeNode(doc);--读取主标签
   rootele := xmldom.createElement(doc,'Roster');--把根标签命名为Roster
   rootnode := xmldom.appendChild(mainnode,xmldom.makeNode(rootele));--把根标Roster加入子节点
   for student in getinfo
    loop
     
     brachele := xmldom.createElement(doc, 'Student');
     
     xmldom.setAttribute(brachele, 'ID', student.sid);
     
     student_node := xmldom.appendChild(rootnode, xmldom.makeNode(brachele));

     brachele := xmldom.createElement(doc, 'NAME');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.sname);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     brachele := xmldom.createElement(doc, 'SEX');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.ssex);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     brachele := xmldom.createElement(doc, 'BIRTHDAY');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.sdob);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     brachele := xmldom.createElement(doc, 'MARK');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.smark);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     brachele := xmldom.createElement(doc, 'SUBJECT');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.ssub);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     brachele := xmldom.createElement(doc, 'NameandSubject');
     brachnode := xmldom.appendChild(student_node, xmldom.makeNode(brachele));
     brachtext := xmldom.createTextNode(doc, student.sname||student.ssub);
     brachnode := xmldom.appendChild(brachnode, xmldom.makeNode(brachtext));
     
     
    end loop;
    xmldom.writeToFile(doc, filename);
    xmldom.freeDocument(doc);
    exception
  when xmldom.INDEX_SIZE_ERR then
     raise_application_error(-20120, 'Index Size error');
  when xmldom.DOMSTRING_SIZE_ERR then
     raise_application_error(-20120, 'String Size error');
  when xmldom.HIERARCHY_REQUEST_ERR then
     raise_application_error(-20120, 'Hierarchy request error');
  when xmldom.WRONG_DOCUMENT_ERR then
     raise_application_error(-20120, 'Wrong doc error');
  when xmldom.INVALID_CHARACTER_ERR then
     raise_application_error(-20120, 'Invalid Char error');
  when xmldom.NO_DATA_ALLOWED_ERR then
     raise_application_error(-20120, 'Nod data allowed error');
  when xmldom.NO_MODIFICATION_ALLOWED_ERR then
     raise_application_error(-20120, 'No mod allowed error');
  when xmldom.NOT_FOUND_ERR then
     raise_application_error(-20120, 'Not found error');
  when xmldom.NOT_SUPPORTED_ERR then
     raise_application_error(-20120, 'Not supported error');
  when xmldom.INUSE_ATTRIBUTE_ERR then
     raise_application_error(-20120, 'In use attr error');
  end proc_tabletoxml;
  --执行过程
begin
 proc_tabletoxml('c:\mydata\mystudent.xml');
end;

posted on 2008-05-06 10:33  庆祝  阅读(530)  评论(0)    收藏  举报