1.函数定义和使用
CREATE FUNCTION add_sal (emp_number IN NUMBER,a IN NUMBER) RETURN NUMBER AS
newsal emp.sal%TYPE;
BEGIN
UPDATE emp SET sal = sal*(1+a) WHERE empno=emp_number;
SELECT sal INTO newsal FROM emp WHERE empno = emp_number;
RETURN newsal;
END add_sal;
/
输出:
set serveroutput on
declare
BEGIN
DBMS_OUTPUT.PUT_LINE(add_sal(7900,0.1));
END;
/
2.创建函数avg_sal,根据部门编号计算该部门所有职工的平均工资
CREATE FUNCTION avgsal(dept_number IN NUMBER) RETURN NUMBER AS
sal_avg emp.sal%TYPE;
BEGIN
SELECT AVG(sal) INTO sal_avg FROM emp WHERE deptno = dept_number;
RETURN sal_avg;
END avgsal;
/
SELECT avgsal(20) FROM dual
3.创建一个存储过程,并定义3个in模式的变量,然后将这3个变量的值插入到emp表empno,ename,job列中
CREATE OR REPLACE PROCEDURE a_insert
(emp_number IN emp.empno%TYPE,
emp_name IN emp.ename%TYPE,
emp_job IN emp.job%TYPE) AS
BEGIN
INSERT INTO emp(empno,ename,job) VALUES(emp_number,emp_name,emp_job);
END a_insert;
/
EXEC a_insert(1000,'Fang','carry');
SELECT empno,ename,job FROM emp WHERE empno=1000;
4.创建存储过程,根据员工编号查询员工的姓名及工资,使用in参数传入员工编号,使用out参数传出姓名及工资。并对未查询到的数据进行错误处理。?????????????????????????????????????????????
CREATE PROCEDURE select_emp
(emp_number IN NUMBER,emp_name OUT VARCHAR2,emp_sal OUT NUMBER) AS
BEGIN
SELECT ename,sal INTO emp_name,emp_sal FROM emp WHERE empno=emp_number;
END select_emp;
/
(DROP PROCEDURE select_emp;)
VARIABLE name VARCHAR2(10);
VARIABLE sal NUMBER;
EXEC select_emp(7900,:name,:sal);
PRINT name;
PRINT sal;
5.创建存储过程为员工涨工资,有部门的员工每人涨500,没有部门的员工每人涨100。
CREATE PROCEDURE addsal
(emp_number IN emp.empno%TYPE) AS
a NUMBER(10);
BEGIN
a:=0;
SELECT deptno INTO a FROM emp WHERE empno=emp_number;
IF a=0 THEN
UPDATE emp SET sal=sal+100 WHERE empno=emp_number;
ELSE
UPDATE emp SET sal=sal+500 WHERE empno=emp_number;
END IF;
END addsal;
/
SELECT sal FROM emp WHERE empno=7900;
EXEC addsal(7900);
SELECT sal FROM emp WHERE empno=7900;
6.创建一个事前触发器,当对emp表的sal列进行修改时,将员工号、加薪前和加薪后的薪资存入temp表中(temp表需要事先建立)。
CREATE TABLE temp(
content VARCHAR2(100),
rtime TIMESTAMP
);
CREATE TRIGGER update_emp
AFTER UPDATE
ON emp
FOR EACH ROW
BEGIN
INSERT INTO temp VALUES('执行了更新操作,empno='||:OLD.empno||'更新前的工资 sal='||:OLD.sal||'new_sal='||:new.sal,SYSDATE);
END update_emp;
/
UPDATE emp SET sal = 1595 WHERE empno=7900;
SELECT * FROM temp;
7.创建一个事前触发器tri_dept,该触发器在insert、update和delete事件下都可以被触发,并且操作的数据对象是emp表。然后要求在触发器执行时输出对emp表所做的具体操作。
create or replace trigger tri_dept
before insert or update or delete
on dept --创建触发器,当dept表发生插入,修改,删除操作时引起该触发器执行
declare
var_tag varchar2(10);--声明一个变量,存储对dept表执行的操作类型
begin
if inserting then --当触发事件是INSERT时
var_tag := '插入';--标识插入操作
elsif updating then --当触发事件是UPDATE时
var_tag := '修改';--标识修改操作
elsif deleting then--当触发事件是DELETE时
var_tag := '删除';--标识删除操作
end if;
insert into dept_log
values(var_tag,sysdate);--向日志表中插入对dept表的操作信息
end tri_dept;
8.创建一个事前行触发器。对修改雇员工资的操作进行合法性检查:没有单位(部门号为空)的员工不能修改工资,修改后的工资要大于修改前的工资;工资增量不能超过原工资的20%,如果违反合法性检查,将输出错误信息。
create or replace trigger judge_emp
before update of sal
on emp
for each row
begin
IF :old.deptno is null then
dbms_output.put_line(:old.empno||'没有部门,不能修改工资');
ELSIF :new.sal<:old.sal then
dbms_output.put_line(:old.empno||'修改后的工资应该大于修改前的工资');
ELSIF :new.sal-:old.sal>=:old.sal*0.2 then
dbms_output.put_line(:old.empno||'工资增量不能超过原工资的20%');
END IF;
end judge_emp;
/
update scott.emp
set sal = sal-100
where deptno is null;
update scott.emp
set sal = sal*1.5
where deptno is null;
9.创建事后触发器,当插入或删除的雇员记录属于30号部门时,输出操作种类和雇员号。输出格式如下所示:
插入30号部门一个记录,雇员号为:18
create or replace trigger aft_emp
after insert or update or delete
on emp
for each row
when(old.deptno=30)
begin
if inserting or updating then
dbms_output.put_line('插入30号部门的一个记录,雇员号为:'||:new.empno);
elsif deleting then
dbms_output.put_line('删除30号部门的一个记录,雇员号为:'||:old.empno);
end if;
end aft_emp;
/
INSERT
INTO scott.emp(empno,ename,deptno)
VALUES(18,'lihao',30);
DELETE
FROM emp
WHERE empno=18;
10.创建一个程序包的“规范”pack_emp,首先在该程序包中声明一个可以获取指定部门的平均工资的函数,然后再声明一个可以实现按照指定比例上调指定职务的工资的存储过程。创建程序包pack_emp的主体,在该主体中实现对应“规范”中声明的函数和存储过程。
CREATE PACKAGE pack_emp
AS
FUNCTION avq_sal2(dno IN scott.emp.deptno%TYPE) RETURN scott.emp.sal%TYPE;
PROCEDURE rise_sal2(ejob IN scott.emp.job%TYPE, range IN number );
END pack_emp;
/
CREATE OR REPLACE PACKAGE BODY pack_emp IS
FUNCTION avq_sal2(dno IN scott.emp.deptno%TYPE)
RETURN scott.emp.sal%TYPE
IS
salary scott.emp.sal%TYPE;
BEGIN
SELECT avg(sal)
INTO salary
FROM scott.emp
WHERE deptno=dno;
RETURN salary;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('未找到相应的部门编号');
RETURN 0;
END avq_sal2;
PROCEDURE rise_sal2(ejob IN scott.emp.job%TYPE, range IN number )
IS
salary scott.emp.sal%TYPE;
BEGIN
update scott.emp
set sal = sal*(1+range)
where job=ejob;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('未找到相应的工作岗位');
END rise_sal2;
END pack_emp ;
/