第一篇:第5章 视图、存储过程和用户自定义函数复习题范文
第5章 视图、存储过程和用户自定函数
1.什么是基本表?什么是视图?两者的区别和联系是什么?
答:
基本表是本身独立存在的表,在 sQL 中一个关系就对应一个表。视图是从一个或几个基本表导出的表。视图本身不独立存储在数据库中,是一个虚表。即数据库中只存放视图的定义而不存放视图对应的数据,这些数据仍存放在导出视图的基本表中。视图在概念上与基本表等同,用户可以如同基本表那样使用视图,可以在视图上再定义视图。.试述视图的优点。
答
(l)视图能够简化用户的操作;(2)视图使用户能以多种角度看待同一数据;(3)视图对重构数据库提供了一定程度的逻辑独立性;(4)视图能够对机密数据提供安全保护。.所有的视图是否都可以更新?为什么?
答:
不是。视图是不实际存储数据的虚表,因此对视图的更新,最终要转换为对基本表的更新。因为有些视图的更新不能惟一有意义地转换成对相应基本表的更新,所以,并不是所有的视图都是可更新的.4 .哪类视图是可以更新的?哪类视图是不可更新的?各举一例说明。
答:基本表的行列子集视图一般是可更新的。若视图的属性来自集函数、表达式,则该视图肯定是不可以更新的。
5.教材P89习题1-5。
第二篇:SQL Sever 2005教案第13章 存储过程及自定义函数
什么是存储过程,在存储在服务器上的T-SQL语句的命名集合,是封装性任务的方法,支持变量及条件的编程。
SQL Server的存储过程与其他编程语言中的过程(包括函数)类似,可以包含数据库操作(调用其他过程)的编程语句,可以接受参数,可以返回状态值以表明成功或失败,以输出参数的形式将多个值返回至调用过程
SQL Server支持五种类型的存储过程:
系统存储过程(sp_):存储在master数据库中。
本地存储过程:在单独的用户数据库中。
临时存储过程:局部的以#开头,全局的以##开头。
远程存储过程:分布式查询支持此功能。
扩展存储过程:在SQL Server环境外执行。
存储过程的优点 封装商务逻辑,若规则或策略改变只需修改存储过程就可以直接使用,屏蔽数据库的详细资料,用户不需要访问底层数据库和数据库对象。提供安全机制,只需要提供存储过程的权限而不需要提供整个数据库中数据的一个权限。另外,存储过程能够通过预编译的语句来确定执行哪一部分而不是都执行。在传输过程中传输的存储过程而不是数据,减少了通信量,能够实现一个较快的执行速度。
create proc liuhaoran as select price from titles where price>15 select title from titles where price<=15
在存储过程里可以包含任何数目和类型的T-SQL语句,但不能包含create proc、create trigger、create view 执行创建存储过程的用户必须是sysadmin、db_owner 或 db_ddladmin角色的成员,或必须拥有 CREATE PROCEDURE 权限 存储过程有大小的限制,最大为128M
存储过程可以传递参数,创建存储过程,定义两个浮点型的参数,无返回值 CREATE PROCEDURE titlespro @Beginningprice float,@Endingprice float AS IF @Beginningprice IS NULL OR @Endingprice IS NULL BEGIN
print 'no price is exits'
RETURN END SELECT price FROM titles WHERE price BETWEEN @Beginningprice AND @Endingprice GO
/*执行语句,输入两个价格值作为参数值*/ exec titlespro 10,19
指定参数的依据和指导原则
所有的输入参数值都应该在存储过程开始的时候进行检查,以尽早捕获缺失值和非法值
应该为参数提供合适的默认值,可以未指定参数值的基础上执行存储过程
一个存储过程最多可以有1024个参数
不同存储过程可以使用相同的参数名 使用参数的指导原则
可以使用@参数=值的格式来指定参数,此方法可以按任意顺序来传递参数
对于有默认值的参数在调用存储过程的过程中可以不指定参数值
存储过程可以使用输出参数
--创建存储过程输入两个输入参数,定义一个输出参数 CREATE PROCEDURE Mathadd @m1 int, @m2 int, @result int OUTPUT--定义输出参数 AS SET @result=@m1+@m2 GO
调用过程如下:
declare @resultvalues int
exec mathadd 12,16,@resultvalues output--输出参数的值赋给变量 print 'The result is: '+convert(char,@resultvalues)
存储过程通过输出参数向调用它的存储过程或客户端返回信息,通过输出参数,存储过程的运行结果可以保留到程序运行结束。输出参数接受需要注意:
调用语句必须包含一个变量名,以接受返回值。
可以在T-SQL语句中使用返回变量 输出参数可以是任意类型,除了text和image 输出参数可以是游标
对于已经创建好的存储过程,如果存储过程需要修改,可以显式地重新编译,但应尽量少做。
在创建存储过程之前通常会检查此存储过程是否存在,如果存在可以选择删除后重建,或改变名字
IF EXISTS(SELECT name FROM sysobjects WHERE name='author_infor' AND type='p')DROP PROCEDURE author_infor GO
修改存储过程使用关键字alter
alter procedure pro_titles @values money--修改存储过程pro_titles as select price,pub_id from titles where price=@values go
删除存储过程使用关键字drop proc,因为存储过程属于数据库对象
drop procedure pro_titles
对于数据库中的所有存储过程或者触发器,如果需要将其全部重新编译,那么可以使用以下语句,EXEC sp_recompile titles--重新编译所有的存储过程或者触发器
在程序中通常会出现因为运行错误而出现的各种错误提示,其大部分都不能被用户容易读懂,因此可以自定义错误信息,来提示用户错误的具体原因。--自定义错误信息
EXEC sp_addmessage
@msgnum = 50010,---错误编号 @severity = 10,----严重级别
@msgtext = 'Customer cannot be deleted.',--错误文本信息 @with_log='true', @lang='us_english'
创建好自定义错误信息之后,就可以在程序中使用错误信息
--调用自定义错误信息
EXEC sp_addmessage 50010,10,'CustomerID not found.',@replace='replace' USE Northwind GO CREATE PROC UpdateCustomerPhone @CustomerID nchar(5)=NULL, @Phone nvarchar(24)=NULL AS IF @CustomerID IS NULL BEGIN
PRINT 'You must supply a valid CustomerID.'
RETURN END /*确认提供了合法的CustomerID */ IF NOT EXISTS(SELECT * FROM Customers WHERE CustomerID=@CustomerID)
BEGIN
RAISERROR(50010,10,1)--该客户不存在。
RETURN
END BEGIN TRANSACTION UPDATE Customers SET Phone =@Phone WHERE CustomerID=@CustomerID /*显示CompanyName的电话号码已更新的消息*/ SELECT 'The phone number for'+@CustomerID +'has been updated to'+ @Phone COMMIT TRANSACTION GO
创建存储过程的方法上面已经介绍结束,如果想要查看存储过程的代码,就需要使用到以下的关键字
--查看存储过程
EXEC sp_helptext UpdateCustomerPhone
而对于以存在的存储过程,在调用的过程由于某些原因需要重新命名的化,使用以下语句
--重命名存储过程
EXEC sp_rename reptq1, newproc
用户自定义函数部分
函数和存储过程同样都有输入和输出参数,单数输入和输出参数的声明方式有些区别--创建函数 USE pubs go CREATE FUNCTION WorkYearWage(@hiredate datetime,--hiredate 表示雇佣日期
@today datetime, @per_wage money)--today 表示当前的日期per_wage 表示每一年工龄应得的工资额 RETURNS money--返回值类型 AS BEGIN DECLARE @WorkYearWage money SET @WorkYearWage =(year(@today)-year(@hiredate))*@per_wage RETURN(@WorkYearWage)--返回的变量 END--结束函数定义 GO-
使用函数参数,当使用命名函数的时候,参数的次序不必按照在函数中声明的次序,但必须包含所有参数,不能省略任何参数
使用函数的过程同以前学习过的系统函数的使用方法想类似,在输出或查询语句中使用函数名及相应的床底若干参数即可。
--使用函数
SELECT pubs.dbo.workyearwage('1991-7-1',getdate(),15)--传参并输出结果
As work_year_wage
在函数的返回值方面可以直接声明返回参数,或者声明返回值类型--计算立方体函数
CREATE FUNCTION CubicVolume(@CubeLength decimal(4,1), @CubeWidth decimal(4,1), @CubeHeight decimal(4,1))--定义输入参数 RETURNS decimal(12,3)--定义返回值类型 AS BEGIN RETURN(@CubeLength * @CubeWidth * @CubeHeight)--返回结果 END
除特定类型的返回值之外,还可以返回表类型的结果集
--内联表值型用户自定义函数
CREATE FUNCTION orderfirms(@productid INT)--定义一个整型参数 RETURNS TABLE--返回值为表的结果集 AS RETURN(SELECT * FROM jobs WHERE min_lvl>@productid)--返回查询结果 GO
或者返回值是一张临时表
--多声明表值型用户自定义函数 USE Northwind go CREATE FUNCTION my_function(@regionParameter varchar(25))--定义一个函数的参数
returns @my_table TABLE--函数返回值为表的结果集,并定义表的结果集如下(city varchar(15)null, companyName varchar(40)not null, contactName varchar(30)null)AS BEGIN INSERT @my_table--从表customers中查询数据插入到@my_table中 SELECT city,companyName,contactName FROM Customers WHERE city=@regionParameter RETURN--返回结果集 END
表值函数:
函数体内只允许如下语句:
赋值语句
流程控制语句
用于定义函数局部数据变量和游标的declare语句
Select语句,将其后的表达式将赋予函数的局部变量
游标操作,仅允许使用fetch语句通过into子句给局部变量赋值,不允许使用fetch语句将数据返回到客户端
针对上面的例子(内嵌表值函数)需要注意的是:
return子句在括号中包含单个select语句,select语句的结果集构成函数所返回的表 函数体不由begin和end分隔
Return指定table作为返回的数据类型
不必定义返回变量的格式,因为它由return子句中的select语句的结果集的格式设置
查看创建用户自定义函数的方式有两种 查看特定用户自定义函数
--查看用户自定义函数 USE pubs go EXEC sp_helptext my_function--调用存储过程 GO
查看所有用户自定义函数
--通过系统表查看用户自定义函数 use pubs go select name, type, crdate from sysobjects where type='FN'--go
当创建的用户自定义函数需要修改时,使用如下语句
--修改函数cubicvolume函数
ALTER FUNCTION CubicVolume--这句表示声明修改用户自定义函数,其他语句不变
(@CubeLength decimal(4,1), @CubeWidth decimal(4,1))--定义输入参数 RETURNS decimal(12,3)--定义返回值类型 AS BEGIN RETURN(@CubeLength * @CubeWidth)--返回结果 END 基本语法和创建的类型,只需要将create更改为alter即可
删除存储过程,由于存储过程为数据库对象因此删除使用drop drop function cubicvolume
第三篇:NX10用户自定义成型刀具和刀库
基于
UGNX10.0用户自定义成型刀具
1:首先打开图档-进入加工模块-平面铣模块(mill-planar)
注:进入任意一个加工模块均可以
2:切换至机床视图-选择创建刀具
注:创建刀具类型只能选择
mill-pianar
3:选择刀具子类型中的-
MILL_USER_DEFINED
确定
4:用户定义刀具对话框如下图、加工区域会出如下刀具
通用的刀具可以通过“段数”
对话框里面的参数创建
5:例如:
A:移除所有“锻数”里面的所有数值
B:输入数值、每输完一组选择“添加新集”
点一
点二
点三
点四
点五
点六
(LL)直线长度输入“3”(LA)直线/圆弧起始角输入“0”
(AR)圆弧半径输入“0”(AS)圆弧扫掠输入“0”
(LL)直线长度输入“5”(LA)直线/圆弧起始角输入“90”
(AR)圆弧半径输入“5”(AS)圆弧扫掠输入“-90”
(LL)直线长度输入“3”(LA)直线/圆弧起始角输入“0”
(AR)圆弧半径输入“0”(AS)圆弧扫掠输入“0”
(LL)直线长度输入“6”(LA)直线/圆弧起始角输入“90”
(AR)圆弧半径输入“0”(AS)圆弧扫掠输入“0”
(LL)直线长度输入“6”(LA)直线/圆弧起始角输入“180”
(AR)圆弧半径输入“0”(AS)圆弧扫掠输入“0”
(LL)直线长度输入“30”(LA)直线/圆弧起始角输入“90”
(AR)圆弧半径输入“0”(AS)圆弧扫掠输入“0”
6:指定刀路跟踪点(回转体刀具可以不用特别指定、在车加工需要指定刀路生
成轨迹的参考点)为圆心。
7:设置刀具其他参数、描述、编号、等至此刀具创建完成、确认即可
8:将刀具创建到刀具库.输入库号如:“fb20161202”选择”刀具导入至刀具库”确定
9:根据需要创建“刀柄”“夹持器”等相关参数最后“确定”
10:从刀具库中调取刀具
选择“创建刀具”—“库”
选择“从库中调用刀具”—“库类选择”—“工具”—“确定”—可以输入创建的库号或直接确定
搜索到库号后选中可以“预览”查看是否是你想要的刀具-确定调出你要的刀具
11:从刀具库中删除创建错误刀具
退出
UG、打开
UG安装路径如:我安装在D盘路径为:D:\Program
Files\Siemens\NX
10.0\MACH\resource\library\tool\metric,文件夹内容如
下:
记事本方式打开:tool_database文件、通过记事本查找功能找到错误刀具库名:
如“fb20161202”刀具
将选中部分全部删除—保存—退出记事本
将
UG打开重新进入刀具库-搜索“fb20161202”刀具—刀具已删除
第四篇:Oracle创建函数和过程
ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
继上篇:ORACLE PL/SQL编程之八:把触发器说透 得到了大家的强力支持,感谢。接下来再下猛药,介绍下一篇,大家一定要支持与推荐呀~!我也才有动力写后面的。
本篇主要内容如下:
6.1 引言 6.2 创建函数 6.3 存储过程 6.3.1 创建过程 6.3.2 调用存储过程 6.3.3 AUTHID
6.3.4 PRAGMA AUTONOMOUS_TRANSACTION 6.3.5 开发存储过程步骤 6.3.6 删除过程和函数 6.3.7 过程与函数的比较
6.1 引言
过程与函数(另外还有包与触发器)是命名的PL/SQL块(也是用户的方案对象),被编译后存储在数据库中,以备执行。因此,其它PL/SQL块可以按名称来使用他们。所以,可以将商业逻辑、企业规则写成函数或过程保存到数据库中,以便共享。过程和函数统称为PL/SQL子程序,他们是被命名的PL/SQL块,均存储在数据库中,并通过输入、输出参数或输入/输出参数与其调用者交换信息。过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据。在本节中,主要介绍:
1. 创建存储过程和函数。2. 正确使用系统级的异常处理和用户定义的异常处理。
3. 建立和管理存储过程和函数。
6.2 创建函数
1.创建函数
语法如下:
CREATE [OR REPLACE] FUNCTION function_name(arg1 [ { IN | OUT | IN OUT }] type1 [DEFAULT value1], [arg2 [ { IN | OUT | IN OUT }] type2 [DEFAULT value1]],......[argn [ { IN | OUT | IN OUT }] typen [DEFAULT valuen]])[ AUTHID DEFINER | CURRENT_USER ] RETURN return_type IS | AS
<类型.变量的声明部分> BEGIN
执行部分
RETURN expression EXCEPTION 异常处理部分 END function_name;
IN,OUT,IN OUT是形参的模式。若省略,则为IN模式。IN模式的形参只能将实参传递给形参,进入函数内部,但只能读不能写,函数返回时实参的值不变。OUT模式的形参会忽略调用时的实参值(或说该形参的初始值总是NULL),但在函数内部可以被读或写,函数返回时形参的值会赋予给实参。IN OUT具有前两种模式的特性,即调用时,实参的值总是传递给形参,结束时,形参的值传递给实参。调用时,对于IN模式的实参可以是常量或变量,但对于OUT和IN OUT模式的实参必须是变量。
一般,只有在确认function_name函数
是新函数或是要更新的函数时,才使用OR REPALCE关键字,否则容易删除有用的函数。
例1.获取某部门的工资总和:
--获取某部门的工资总和 CREATE OR REPLACE FUNCTION get_salary(Dept_no NUMBER, Emp_count OUT NUMBER)RETURN NUMBER IS
V_sum NUMBER;BEGIN
SELECT SUM(SALARY), count(*)INTO V_sum, emp_count FROM EMPLOYEES WHERE DEPARTMENT_ID=dept_no;RETURN v_sum;EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('你需要的数据不存在!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END get_salary;
2.函数的调用
函数声明时所定义的参数称为形式参数,应用程序调用时为函数传递的参数称为实际参数。应用程序在调用函数时,可以使用以下三种方法向函数传递参数:
第一种参数传递格式:位置表示法。
即在调用时按形参的排列顺序,依次写出实参的名称,而将形参与实参关联起来进行传递。用这种方法进行调用,形参与实参的名称是相互独立,没有关系,强调次序才是重要的。
格式为:
argument_value1[,argument_value2 …]
例2:计算某部门的工资总和:
DECLARE
V_num NUMBER;V_sum NUMBER;BEGIN
V_sum :=get_salary(10, v_num);DBMS_OUTPUT.PUT_LINE('部门号为:10的工资总和:'||v_sum||',人数为:'||v_num);END;
第二种参数传递格式:名称表示法。
即在调用时按形参的名称与实参的名称,写出实参对应的形参,而将形参与实参关联起来进行传递。这种方法,形参与实参的名称是相互独立的,没有关系,名称的对应关系才是最重要的,次序并不重要。
格式为:
argument => parameter [,…]
其中:argument 为形式参数,它必须与函数定
义时所声明的形式参数名称相同parameter 为实际参数。
在这种格式中,形势参数与实际参数成对出现,相互间关系唯一确定,所以参数的顺序可以任意排列。例3:计算某部门的工资总和:
DECLARE
V_num NUMBER;V_sum NUMBER;BEGIN
V_sum :=get_salary(emp_count => v_num, dept_no => 10);DBMS_OUTPUT.PUT_LINE('部门号为:10的工资总和:'||v_sum||',人数为:'||v_num);END;
第三种参数传递格式:组合传递。
即在调用一个函数时,同时使用位置表示法和名称表示法为函数传递参数。采用这种参数传递方法时,使用位置表示法所传递的参数必须放在名称表示法所传递的参数前面。也就是说,无论函数具有多少个参数,只要其中有一个参数使用名称表示法,其后所有的参数都必须使用名称表示法。
例4:
CREATE OR REPLACE FUNCTION demo_fun(Name VARCHAR2,--注意VARCHAR2不能给精度,如:VARCHAR2(10),其它类似 Age INTEGER, Sex VARCHAR2)RETURN VARCHAR2 AS
V_var VARCHAR2(32);BEGIN
V_var := name||':'||TO_CHAR(age)||'岁.'||sex;RETURN v_var;END;
DECLARE
Var VARCHAR(32);BEGIN
Var := demo_fun('user1', 30, sex => '男');DBMS_OUTPUT.PUT_LINE(var);
Var := demo_fun('user2', age => 40, sex => '男');DBMS_OUTPUT.PUT_LINE(var);
Var := demo_fun('user3', sex => '女', age => 20);DBMS_OUTPUT.PUT_LINE(var);END;
无论采用哪一种参数传递方法,实际参数和形式参数之间的数据传递只有两种方法:传址法和传值法。所谓传址法是指在调用函数时,将实际参数的地址指针传递给形式参数,使形式参数和实际参数指向内存中的同一区域,从而实现参数数据的传递。这种方法又称作参照法,即形式参数参照实际参数数据。输入参数均采用传址法传递数据。传值法是指将实际参数的数据拷贝到形式参数,而不是传递实际参数的地址。默认时,输出参数和输入/输出参数均采用传值法。在函数调用时,ORACLE将实际参数数据拷贝到输入/输出参数,而当函数正常运行退出时,又将输出形式参数和输入/输出形式参数数据拷贝到实际参数变量中。
3.参数默认值
在CREATE OR REPLACE FUNCTION 语句中声明函数参数时可以使用DEFAULT关键字为输入参数指定默认值。
例5:
CREATE OR REPLACE FUNCTION demo_fun(Name VARCHAR2, Age INTEGER, Sex VARCHAR2 DEFAULT '男')RETURN VARCHAR2 AS
V_var VARCHAR2(32);BEGIN
V_var := name||':'||TO_CHAR(age)||'岁.'||sex;RETURN v_var;END;
具有默认值的函数创建后,在函数调用时,如果没有为具有默认值的参数提供实际参数值,函数将使用该参数的默认值。但当调用者为默认参数提供实际参数时,函数将使用实际参数值。在创建函数时,只能为输入参数设置默认值,而不能为输入/输出参数设置默认值。
DECLARE
var VARCHAR(32);BEGIN
Var := demo_fun('user1', 30);DBMS_OUTPUT.PUT_LINE(var);
Var := demo_fun('user2', age => 40);DBMS_OUTPUT.PUT_LINE(var);
Var := demo_fun('user3', sex => '女', age => 20);
DBMS_OUTPUT.PUT_LINE(var);END;6.3 存储过程
6.3.1 创建过程
建立存储过程
在 ORACLE SERVER上建立存储过程,可以被多个应用程序调用,可以向存储过程传递参数,也可以向存储过程传回参数.创建过程语法:
CREATE [OR REPLACE] PROCEDURE procedure_name([arg1 [ IN | OUT | IN OUT ]] type1 [DEFAULT value1], [arg2 [ IN | OUT | IN OUT ]] type2 [DEFAULT value1]],......[argn [ IN | OUT | IN OUT ]] typen [DEFAULT valuen])[ AUTHID DEFINER | CURRENT_USER ] { IS | AS } <声明部分> BEGIN
<执行部分> EXCEPTION <可选的异常错误处理程序> END procedure_name;
说明:相关参数说明参见函数的语法说明。
例6.用户连接登记记录;
CREATE TABLE logtable(userid VARCHAR2(10), logdate date);
CREATE OR REPLACE PROCEDURE logexecution IS BEGIN
INSERT INTO logtable(userid, logdate)VALUES(USER, SYSDATE);END;
例7.删除指定员工记录;
CREATE OR REPLACE PROCEDURE DelEmp(v_empno IN employees.employee_id%TYPE)AS
No_result EXCEPTION;BEGIN
DELETE FROM employees WHERE employee_id = v_empno;IF SQL%NOTFOUND THEN RAISE no_result;END IF;DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'的员工已被删除!');EXCEPTION WHEN no_result THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:你需要的数据不存在!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END DelEmp;
例8.插入员工记录:
CREATE OR REPLACE PROCEDURE InsertEmp(v_empno in employees.employee_id%TYPE, v_firstname in employees.first_name%TYPE, v_lastname in employees.last_name%TYPE, v_deptno in employees.department_id%TYPE)AS
empno_remaining EXCEPTION;PRAGMA EXCEPTION_INIT(empno_remaining,-1);/*-1 是违反唯一约束条件的错误代码 */ BEGIN
INSERT INTO EMPLOYEES(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, HIRE_DATE,DEPARTMENT_ID)VALUES(v_empno, v_firstname,v_lastname, sysdate, v_deptno);DBMS_OUTPUT.PUT_LINE('温馨提示:插入数据记录成功!');EXCEPTION WHEN empno_remaining THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:违反数据完整性约束!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END InsertEmp;
例9.使用存储过程向 departments表中插入数据。CREATE OR REPLACE PROCEDURE insert_dept(v_dept_id IN departments.department_id%TYPE, v_dept_name IN departments.department_name%TYPE, v_mgr_id IN departments.manager_id%TYPE, v_loc_id IN departments.location_id%TYPE)IS
ept_null_error EXCEPTION;PRAGMA EXCEPTION_INIT(ept_null_error,-1400);ept_no_loc_id EXCEPTION;PRAGMA EXCEPTION_INIT(ept_no_loc_id,-2291);BEGIN
INSERT INTO departments(department_id, department_name, manager_id, location_id)VALUES
(v_dept_id, v_dept_name, v_mgr_id, v_loc_id);DBMS_OUTPUT.PUT_LINE('插入部门'||v_dept_id||'成功');EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20000, '部门编码不能重复');WHEN ept_null_error THEN
RAISE_APPLICATION_ERROR(-20001, '部门编码、部门名称不能为空');WHEN ept_no_loc_id THEN
RAISE_APPLICATION_ERROR(-20002, '没有该地点');END insert_dept;
/*调用实例一: DECLARE ept_20000 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20000,-20000);ept_20001 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20001,-20001);ept_20002 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20002,-20002);BEGIN insert_dept(300, '部门300', 100, 2400);insert_dept(310, NULL, 100, 2400);insert_dept(310, '部门310', 100, 900);EXCEPTION WHEN ept_20000 THEN DBMS_OUTPUT.PUT_LINE('ept_20000部门编码不能重复');WHEN ept_20001 THEN DBMS_OUTPUT.PUT_LINE('ept_20001部门编码、部门名称不能为空');WHEN ept_20002 THEN DBMS_OUTPUT.PUT_LINE('ept_20002没有该地点');WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('others出现了其他异常错误');END;
调用实例二: DECLARE ept_20000 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20000,-20000);ept_20001 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20001,-20001);ept_20002 EXCEPTION;PRAGMA EXCEPTION_INIT(ept_20002,-20002);BEGIN insert_dept(v_dept_name => '部门310', v_dept_id => 310, v_mgr_id => 100, v_loc_id => 2400);insert_dept(320, '部门320', v_mgr_id => 100, v_loc_id => 900);EXCEPTION WHEN ept_20000 THEN DBMS_OUTPUT.PUT_LINE('ept_20000部门编码不能重复');WHEN ept_20001 THEN DBMS_OUTPUT.PUT_LINE('ept_20001部门编码、部门名称不能为空');WHEN ept_20002 THEN DBMS_OUTPUT.PUT_LINE('ept_20002没有该地点');WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('others出现了其他异常错误');END;*/
6.3.2 调用存储过程
存储过程建立完成后,只要通过授权,用户就可以在SQLPLUS、ORACLE开发工具或第三方开发工具中来调用运行。对于参数的传递也有三种:按位置传递、按名称传递和组合传递,传递方法与函数的一样。ORACLE 使用EXECUTE 语句来实现对存储过程的调用:
EXEC[UTE] procedure_name(parameter1, parameter2…);
例10: EXECUTE logexecution;
例11:查询指定员工记录;
CREATE OR REPLACE PROCEDURE QueryEmp(v_empno IN employees.employee_id%TYPE, v_ename OUT employees.first_name%TYPE, v_sal OUT employees.salary%TYPE)AS BEGIN
SELECT last_name || last_name, salary INTO v_ename, v_sal FROM employees WHERE employee_id = v_empno;DBMS_OUTPUT.PUT_LINE('温馨提示:编码为'||v_empno||'的员工已经查到!');EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:你需要的数据不存在!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END QueryEmp;--调用
DECLARE
v1 employees.first_name%TYPE;v2 employees.salary%TYPE;BEGIN
QueryEmp(100, v1, v2);DBMS_OUTPUT.PUT_LINE('姓名:'||v1);DBMS_OUTPUT.PUT_LINE('工资:'||v2);QueryEmp(103, v1, v2);DBMS_OUTPUT.PUT_LINE('姓名:'||v1);DBMS_OUTPUT.PUT_LINE('工资:'||v2);QueryEmp(104, v1, v2);DBMS_OUTPUT.PUT_LINE('姓名:'||v1);DBMS_OUTPUT.PUT_LINE('工资:'||v2);END;
例12.计算指定部门的工资总和,并统计其中的职工数量。
CREATE OR REPLACE PROCEDURE proc_demo(dept_no NUMBER DEFAULT 10, sal_sum OUT NUMBER, emp_count OUT NUMBER)IS BEGIN
SELECT SUM(salary), COUNT(*)INTO sal_sum, emp_count FROM employees WHERE department_id = dept_no;EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:你需要的数据不存在!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END proc_demo;
DECLARE V_num NUMBER;V_sum NUMBER(8, 2);BEGIN
Proc_demo(30, v_sum, v_num);DBMS_OUTPUT.PUT_LINE('温馨提示:30号部门工资总和:'||v_sum||',人数:'||v_num);Proc_demo(sal_sum => v_sum, emp_count => v_num);DBMS_OUTPUT.PUT_LINE('温馨提示:10号部门工资总和:'||v_sum||',人数:'||v_num);END;
在PL/SQL 程序中还可以在块内建立本地函数和过程,这些函数和过程不存储在数据库中,但可以在创建它们的PL/SQL 程序中被重复调用。本地函数和过程在PL/SQL 块的声明部分定义,它们的语法格式与存储函数和过程相同,但不能使用CREATE OR REPLACE 关键字。
例13:建立本地过程,用于计算指定部门的工资总和,并统计其中的职工数量;
DECLARE V_num NUMBER;V_sum NUMBER(8, 2);PROCEDURE proc_demo(Dept_no NUMBER DEFAULT 10, Sal_sum OUT NUMBER, Emp_count OUT NUMBER)IS BEGIN
SELECT SUM(salary), COUNT(*)INTO sal_sum, emp_count FROM employees WHERE department_id=dept_no;EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('你需要的数据不存在!');WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);END proc_demo;--调用方法: BEGIN
Proc_demo(30, v_sum, v_num);DBMS_OUTPUT.PUT_LINE('30号部门工资总和:'||v_sum||',人数:'||v_num);Proc_demo(sal_sum => v_sum, emp_count => v_num);DBMS_OUTPUT.PUT_LINE('10号部门工资总和:'||v_sum||',人数:'||v_num);END;
6.3.3 AUTHID 过程中的AUTHID 指令可以告诉ORACLE,这个过程使用谁的权限运行.默任情况下,存储过程会作为调用者的过程运行,但是具有设计者的特权.这称为设计者权利运行.
例14:建立过程,使用
Connect HR/qaz DROP TABLE logtable;CREATE table logtable(userid VARCHAR2(10), logdate date);
CREATE OR REPLACE PROCEDURE logexecution AUTHID DEFINER IS BEGIN
INSERT INTO logtable(userid, logdate)VALUES(USER, SYSDATE);END;
GRANT EXECUTE ON logexecution TO PUBLIC;
CONNECT / AS SYSDBA GRANT CONNECT TO testuser1 IDENTIFIED BY userpwd1;
CONNECT testuser1/userpwd1 INSERT INTO HR.LOGTABLE VALUES(USER, SYSDATE);EXECUTE HR.logexecution
AUTOID DEFINER; CONNECT HR/qaz SELECT * FROM HR.logtable;
例15:建立过程,使用
CONNECT HR/qaz
CREATE OR REPLACE PROCEDURE logexecution AUTHID CURRENT_USER IS BEGIN
INSERT INTO logtable(userid, logdate)VALUES(USER, SYSDATE);END;
GRANT EXECUTE ON logexecution TO PUBLIC;
CONNECT testuser1/userpwd1 INSERT INTO HR.LOGTABLE VALUES(USER, SYSDATE);EXECUTE HR.logexecution
AUTOID CURRENT_USER;
6.3.4 PRAGMA AUTONOMOUS_TRANSACTION
ORACLE8i 可以支持事务处理中的事务处理的概念.这种子事务处理可以完成它自己的工作,独立于父事务处理进行提交或者回滚.通过使用这种方法,开发者就能够这样的过程,无论父事务处理是提交还是回滚,它都可以成功执行.
例16:建立过程,使用自动事务处理进行日志记录;
DROP TABLE logtable;
CREATE TABLE logtable(Username varchar2(20), Dassate_time date, Mege varchar2(60));
CREATE TABLE temp_table(N number);
CREATE OR REPLACE PROCEDURE log_message(p_message varchar2)AS PRAGMA AUTONOMOUS_TRANSACTION;BEGIN
INSERT INTO logtable VALUES(user, sysdate, p_message);COMMIT;END log_message;BEGIN
Log_message(‘About to insert into temp_table‘);
INSERT INTO temp_table VALUES(1);Log_message(‘Rollback to insert into temp_table‘);
ROLLBACK;END;
SELECT * FROM logtable;SELECT * FROM temp_table;
例17:建立过程,没有使用自动事务处理进行日志记录;
CREATE OR REPLACE PROCEDURE log_message(p_message varchar2)AS BEGIN
INSERT INTO logtable VALUES(user, sysdate, p_message);COMMIT;END log_message;BEGIN
Log_message('About to insert into temp_table');INSERT INTO temp_table VALUES(1);Log_message('Rollback to insert into temp_table');ROLLBACK;END;
SELECT * FROM logtable;SELECT * FROM temp_table;
6.3.5 开发存储过程步骤
开发存储过程、函数、包及触发器的步骤如下:
6.3.5.1 使用文字编辑处理软件编辑存储过程源码 使用文字编辑处理软件编辑存储过程源码,要用类似WORD 文字处理软件进行编辑时,要将源码存为文本格式。
6.3.5.2 在SQLPLUS或用调试工具将存储过程程序进行解释
在SQLPLUS或用调试工具将存储过程程序进行解释;
在SQL>下调试,可用START 或GET 等ORACLE命令来启动解释。如: SQL>START c:stat1.sql
如果使用调式工具,可直接编辑和点击相应的按钮即可生成存储过程。
6.3.5.3 调试源码直到正确
我们不能保证所写的存储过程达到一次就正确。所以这里的调式是每个程序员必须进行的工作之一。在SQLPLUS下来调式主要用的方法是:
使用 SHOW ERROR命令来提示源码的错误位置;
使用 user_errors 数据字典来查看各存储过程的错
误位置。
6.3.5.4 授权执行权给相关的用户或角色
如果调式正确的存储过程没有进行授权,那就只有建立者本人才可以运行。所以作为应用系统的一部分的存储过程也必须进行授权才能达到要求。在SQL*PLUS下可以用GRANT命令来进行存储过程的运行授权。
GRANT语法:
GRANT system_privilege | role TO user | role | PUBLIC [WITH ADMIN OPTION]
GRANT object_privilege | ALL ON schema.object TO user | role | PUBLIC [WITH GRANT OPTION]
--例子:
CREATE OR REPLACE PUBLIC SYNONYM dbms_job FOR dbms_job
GRANT EXECUTE ON dbms_job TO PUBLIC WITH GRANT OPTION
6.3.5.5 与过程相关数据字典
USER_SOURCE, ALL_SOURCE, DBA_SOURCE, USER_ERRORS, ALL_PROCEDURES,USER_OBJECTS,ALL_OBJECTS,DBA_OBJECTS
相关的权限:
CREATE ANY PROCEDURE DROP ANY PROCEDURE
在SQL*PLUS 中,可以用DESCRIBE 命令查看过程的名字及其参数表。
DESC[RIBE] Procedure_name;
6.3.6 删除过程和函数
1.删除过程
可以使用DROP PROCEDURE命令对不需要的过程进行删除,语法如下:
DROP PROCEDURE [user.]Procudure_name;
2.删除函数
可以使用DROP FUNCTION 命令对不需要的函数进行删除,语法如下:
DROP FUNCTION [user.]Function_name;
--删除上面实例创建的存储过程与函数 DROP PROCEDURE logexecution;DROP PROCEDURE delemp;DROP PROCEDURE insertemp;DROP PROCEDURE fireemp;DROP PROCEDURE queryemp;DROP PROCEDURE proc_demo;DROP PROCEDURE log_message;DROP FUNCTION demo_fun;DROP FUNCTION get_salary;
6.3.7 过程与函数的比较
使用过程与函数具有如下优点:
1、共同使用的代码可以只需要被编写和测试一次,而被需要该代码的任何应用程序(如:.NET、C++、JAVA、VB程序,也可以是DLL库)调用。
2、这种集中编写、集中维护更新、大家共享(或重用)的方法,简化了应用程序的开发和维护,提高了效率与性能。
3、这种模块化的方法,使得可以将一个复杂的问题、大的程序逐步简化成几个简单的、小的程序部分,进行分别编写、调试。因此使程序的结构清晰、简单,也容易实现。
4、可以在各个开发者之间提供处理数据、控制流程、提示信息等方面的一致性。
5、节省内存空间。它们以一种压缩的形式被存储在外存中,当被调用时才被放入内存进行处理。并且,如果多个用户要执行相同的过程或函数时,就只需要在内存中加载一个该过程或函数。
6、提高数据的安全性与完整性。通过把一些对数据的操作放到过程或函数中,就可以通过是否授予用户有执行该过程或的权限,来限制某些用户对数据进行这些操作。
过程与函数的相同功能有:
1、都使用IN模式的参数传入数据、OUT模式的参数返
回数据。
2、输入参数都可以接受默认值,都可以传值或传引导。
3、调用时的实际参数都可以使用位置表示法、名称表示
法或组合方法。
4、都有声明部分、执行部分和异常处理部分。
5、其管理过程都有创建、编译、授权、删除、显示依赖
关系等。
使用过程与函数的原则:
1、如果需要返回多个值和不返回值,就使用过程;如果只需要返回一个值,就使用函数。
2、过程一般用于执行一个指定的动作,函数一般用于计算和返回一个值。
3、可以SQL语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。所以这是函数的特色。
第五篇:6.用户自定义控件中 Control Type Def 和 Strict Type Def的区别
为了解释清楚,先定义一下要用到的概念。我们把以.ctl 文件名定义的控件叫做用户自定义控件,把通过拖拽或打开这个.ctl 文件在 VI 上生成的控件叫做实例。
LabVIEW 的用户自定义控件包括了三种定义形式:打开一个.ctl 文件,在它上方的“control”下拉条中有三个选择,分别是无关联控件(Control)、类型定义(Type Def.)或者严格类型定义(Strict Type Def.)。
无关联控件是指这个控件与它的实例之间没有任何关联。例如,你制作了一个漂亮的按钮控件保存在.ctl 文件中。需要用到它时,通过拖拽或打开这个.ctl 文件就可以在 VI 中生成这个用户自定义控件的一个实例。这个实例一旦生成,就和原用户自定义控件无任何关联了。无论是你修改这个实例,还是修改原用户自定义控件,都不会对另一方产生任何影响。
类型定义控件是指实例控件与用户自定义控件的空间类型是相关联的。比如,你的用户自定义控件是一个数值型控件,那么它的所有实例控件也都是数值型的。如果我们在.ctl 文件中把用户自定义控件的类型改为字符串,那么它已有的所有实例都将自动变成字符串类型。
有时候,只是类型相关联还不够。比如对于 Ring(Enum,Combo Box)这类的控件来说,如果在用户自定义控件中添加了一项内容(item),一般总是希望它所有的实例也同时添加这一选项。如果使用类型定义控件,因为控件类型没变,还是 Ring,实例们是不会自动跟随更新的。这时就需要使用严格类型定义控件。选择严格类型定义后,不但实例与用户自定义控件的类型是相关联的,其他一些控件属性,比如颜色等等,也是相关联的。
使用严格类型定义时有一点容易被误解:严格类型定义只是与实例控件相关联,由它生成的实例常量的属性是不与之关联的。实例常量是指通过拖拽或生成常量等方法,在程序框图上生成的一个与.ctl 文件相关联的常量。比如在 Ring 型用户自定义控件中添加了一项内容,相关的实例常量是不会发生任何改变的。很多人按常理想,认为常量也应当自动更新,但事实上不行。这也是我不采用它做常量定义的原因之
一。(参见:在 LabVIEW 中使用常量定义)