SQL Server与ORACLE数据库存储过程编写的几个不同之处
一直在使用SQL Server数库的存储过程进行业务数据处理,现在ORACLE上进行存储过程应用,感觉没有MSSQL的方便灵活,总结了以下几点区别:
1、入参数据类型不要书写长度。比如:userName VARCHAR2(100) 是不正确的。
2、过程内变量声明必须在关键字IS/AS后,过程的开始BEGIN之间,且无需DECLARE关键字,变量名也无需@符号开头。而MSSQL是可以在过程体内任意位置通过Declare声明的。
3、浮点类型的变量一定要声明成NUMBER类型,DECIMAL会有精度问题导致取值不是所期望的值。
4、游标的使用如果是动态游标(并不是一开始就固定创建的,而是根据不同条件的生成的),必须先声明动态游标的类型和变量名。比如下例代码中的:
TYPE ref_cur IS REF CURSOR;
cur_stock REF_CUR; --库存处理游标
5、SELECT语句对变量赋值语法:SELECT col1,col2 INTO var1,var2 FROM table1 WHERE ROWNUM=1,而MSSQL的语法是:SELECT @var1=col1,@var2=col2 FROM table1 WHERE id=1。
6、如果上5中所说的变量赋值没有检索到记录还会触发 NO_DATA_FOUND THEN异常,可以用 EXCEPTION对异常进行捕获处理。而MSSQL没检索到数据变量会被赋值为NULL值。
7、ORACLE的UPDATE语句内不能对变量进行更新操作,这一点真的是太不爽啦!!!。MSSQL是可以,例:DELCARE @NUM=0; UPDATE table1 SET @NUM=@NUM+1,col1=@NUM
CREATE OR REPLACE PROCEDURE JUNAN.P_OPD_QUOTN_INS (
--门诊医嘱签名过程 liuyc 20210902
writeId IN INT, --待签名医嘱记录id
operateId IN INT, --操作员id
exprdate IN INT, --减少库存时批次:0不控制效期,1控制效期
upstatus IN INT, --是否更新医嘱状态为已签名
amount OUT NUMBER, --出库销售金额
mess OUT VARCHAR2 --OK为执行成功
)
IS
--本组变量保存医嘱信息
ow_drugId VARCHAR2(30); --药品id
ow_drugTypeId VARCHAR2(30); --药品类别id
ow_unitName VARCHAR2(30); --药品单位名称
ow_unitId NUMBER(12,0); --药品包装单位id
ow_count NUMBER(12,4); --药品数量
ow_baseCount NUMBER(12,4); --按基本单位算的药品数量
ow_status VARCHAR2(4); --医嘱状态
ow_patientId NUMBER(12,0); --患者id
ow_deptId NUMBER(12,0); --药房id
ow_hosId NUMBER(12,0); --医院id
ow_relation NUMBER(12,6); --药品包装单位换算比
--本组变量保存临时库存批次信息
st_rowid ROWID; --库存批次表行系统rowid
st_id INT; --库存游标保存变量 库存记录id
st_unitId INT; --库存包装单位id
st_relation NUMBER(22,6); --换算比
st_count NUMBER(22,4); --库存数量
st_price NUMBER(22,6); --药房包装单位的零售价格
--其他变量
per_quantity NUMBER(22,4) :=0; --每次库存循环处理数量
per_amount NUMBER(22,2) :=0; --每次库存循环处理金额
total_quantity NUMBER(22,4) :=0; --累计数量
total_amount NUMBER(22,2) :=0; --累计金额
operateName VARCHAR2(60); --操作员姓名
TYPE ref_cur IS REF CURSOR;
cur_stock REF_CUR; --库存处理游标
BEGIN
mess:='';
--取得医嘱信息
BEGIN
SELECT DOCTOR_ORDER_ID,DRUG_COUNT,DRUG_COUNT_UNIT,DRUG_UNIT_ID,ORDER_STATUS_ID,PATIENT_ID,EXECUTIVE_SECTION_ID,HOSPITAL_ID
INTO ow_drugId,ow_count,ow_unitName,ow_unitId,ow_status,ow_patientId,ow_deptId,ow_hosId
FROM T_OPD_DOCTOR_ORDER_WRITE WHERE DOCTOR_ORDER_TYPE_ID='drug' AND id=writeId FOR UPDATE NOWAIT;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='医嘱记录不存在!';
RETURN;
END;
--只有医嘱状态0未签名、10审核驳回时可以做签名操作
IF NVL(ow_status,'0') NOT IN ('0','10') THEN
mess:=CONCAT('医嘱记录签名状态无效,值:',NVL(ow_status,''));
RETURN;
END IF;
--取得门诊处方药品包装单位换算比,药品类别id
BEGIN
SELECT a.RELATION,b.DRUG_TYPE_ID INTO ow_relation,ow_drugTypeId from T_PHARMACY_DRUG_PACKAGE a
INNER JOIN T_PHARMACY_DRUG b ON b.ID=A.DRUG_ID
WHERE ROWNUM=1 and a.STATUS='1' and a.ID=ow_unitId;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='查询药品包装单位换算比无数据!';
RETURN;
END;
IF ow_relation IS NULL THEN
mess:='药品包装单位换算比为null!';
RETURN;
END IF;
--取操作员信息
BEGIN
SELECT name INTO operateName FROM T_SYS_OPERATOR WHERE id=operateId;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='操作员记录不存在!';
RETURN;
END;
IF NVL(ow_status,'')!=0 THEN
mess:=CONCAT('医嘱记录签名状态无效,值:',NVL(ow_status,''));
RETURN;
END IF;
--换算医嘱药品数量为基本单位数量
ow_baseCount:=ROUND(ow_count*ow_relation,4);
--打开动态游标,将临时库存中本药品有效批次库存的行id保存用于后续扣减处理
open cur_stock FOR
SELECT ROWID FROM T_DRUGSTORE_DRUG_STOCK_TEMP T
WHERE T.STATUS = '1' AND T.BATCH_INVALID = '1'
AND (CASE WHEN exprdate=1 THEN T.EXPIRATION_DATE ELSE TO_DATE('9999-12-31','YYYY-MM-dd') END) >= trunc(sysdate)
AND T.QUANTITY > 0 AND T.DEPT_ID=ow_deptId AND T.DRUG_ID =ow_drugId
order by EXPIRATION_DATE;
LOOP
--遍历库存记录进行库存处理
FETCH CUR_STOCK INTO st_rowid;
exit when cur_stock%NOTFOUND;
--取得当前id批次库存信息并锁定
BEGIN
SELECT ID,NEW_MAX_PACKAGE_UNIT_ID,RELATION,QUANTITY,DRUGSTORE_RETAIL_PRICE
INTO st_id,st_unitId,st_relation,st_count,st_price FROM T_DRUGSTORE_DRUG_STOCK_TEMP WHERE QUANTITY > 0 AND ROWID=ST_ROWID
FOR UPDATE;
EXCEPTION WHEN NO_DATA_FOUND THEN
CONTINUE;
END;
--计算本批次扣减库存数量:批次库存小于等于待出库数量时取本批结余数,否则用待出库数
PER_QUANTITY:=(CASE WHEN st_count<=ow_baseCount THEN st_count ELSE ow_baseCount END);
--计算销售金额
PER_AMOUNT:=ROUND(PER_QUANTITY/ST_RELATION*ST_PRICE,2);
--更新本批次结存数量
UPDATE T_DRUGSTORE_DRUG_STOCK_TEMP SET QUANTITY=QUANTITY-PER_QUANTITY,UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE
WHERE QUANTITY>=PER_QUANTITY AND ROWID=st_rowid;
IF SQL%ROWCOUNT<1 THEN
mess:='扣减临时库存更新了0行,库存数量有变化请重试!';
RETURN;
END IF;
--写入药品划价记录
INSERT INTO T_OPD_QUOTN (ID, HOSPITAL_ID, DEPT_ID, ORDER_WRITE_ID, STOCK_ID, DRUG_ID, UNIT_NAME, QUANTITY, PRICE, AMOUNT, RETURN_QUANTITY,
CREATE_TIME,CREATE_OPER)
VALUES (SEQ_OPD_QUOTN.NEXTVAL,OW_HOSID,OW_DEPTID,writeId,ST_ID,OW_DRUGID,OW_UNITNAME,
ROUND(PER_QUANTITY/ow_relation,4),ROUND(PER_AMOUNT*ow_relation/PER_QUANTITY,4),PER_AMOUNT,0,SYSDATE,operateName);
--更新累计出库数量和金额,待出库基本单位数量
TOTAL_QUANTITY:=TOTAL_QUANTITY+PER_QUANTITY;
TOTAL_AMOUNT:=TOTAL_AMOUNT+PER_AMOUNT;
ow_baseCount:=ow_baseCount-PER_QUANTITY;
IF ow_baseCount=0 THEN
EXIT; --库存数量足额扣减退出循环
END IF;
END LOOP;
CLOSE CUR_STOCK;
--循环结束判断待出库数量如果为非零,则说明不足出库
IF ow_baseCount!=0 THEN
mess:=CONCAT('临时库存不足,待扣减基本单位数量:',TO_CHAR(ow_baseCount));
RETURN;
END IF;
--库存扣减正常,更新门诊患者费用表金额信息,医嘱金额返回调用由代码修改
UPDATE T_OPD_DOCTOR_COST SET TOTAL_SUM=TOTAL_AMOUNT,PRICE=ROUND(TOTAL_AMOUNT/ORDER_COUNT,4),UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE
WHERE TOTAL_SUM!=TOTAL_AMOUNT AND HOSPITAL_ID=OW_HOSID AND ORDER_WRITE_ID=writeId;
--更新医嘱药品费用金额
UPDATE T_OPD_DOCTOR_ORDER_WRITE SET SUM_PRICE=TOTAL_AMOUNT,
PRICE=(CASE WHEN DRUG_COUNT=0 THEN 0 ELSE ROUND(TOTAL_AMOUNT/DRUG_COUNT,4) END),
ORDER_STATUS_ID=(CASE WHEN upstatus=1 THEN '1' ELSE ORDER_STATUS_ID END),UPDATE_DATE=SYSDATE
WHERE id=writeId;
amount:=TOTAL_AMOUNT;
mess:='OK';
EXCEPTION
WHEN NO_DATA_FOUND THEN
mess:='查询记录数据为空!';
WHEN OTHERS THEN
mess := SUBSTR(SQLERRM,1,2000);
END P_OPD_QUOTN_INS;
/
SQL Server与ORACLE数据库存储过程编写的几个不同之处的更多相关文章
- sql server和oracle数据库
sql server和oracle数据库安装按照官方教程即可:以及他们相应的管理工具,sql server management studio自带的,oracle的管理工具PLSQL需要单独下载安装, ...
- 关于sql server远程访问Oracle数据库 OpenQuery查询返回多条数据的问题
在Sql Server远程访问Oracle 中的数据库表时: 远程语法通常为: select * from OpenQuery(Oracle链接服务器名称,‘查询语句’) eg: select * f ...
- mysql、sql server、oracle数据库分页查询及分析(操作手册)
1.mysql分页查询 方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实 ...
- ms sql server,oracle数据库实现拼接一列的多行内容
项目中要将查询出的一列的多行内容拼接成一行,如下图:ypmc列. ms sql server: 网上查到相关资料如下:http://blog.csdn.net/rolamao/article/deta ...
- sql server远程访问Oracle数据库
在sql server上新建了连接服务器后 在指定的链接服务器上执行指定的传递查询. 该服务器是 OLE DB 数据源. OPENQUERY 可以在查询的 FROM 子句中引用,就好象它是一个表名. ...
- SQL Server,MySql,Oracle数据库的默认端口号
SQL Server默认端口号为:1433 MySQL 默认端口号为:3306 Oracle 默认端口号为:1521
- SQL Server 进阶 01 数据库的设计
SQL Server 进阶 01 数据库的设计 本篇目录 课程内容回顾及介绍 为什么需要规范的数据库设计 设计数据库的步骤 绘制E-R(实体-关系)图 实体-关系模型 如何将E-R图转换为表 数据规范 ...
- 数据库管理工具神器-DataGrip,可同时管理多个主流数据库[SQL Server,MySQL,Oracle等]连接
前言 DataGrip:Jet Brains出品的一款数据库管理工具(没错,是Jet Brains出品,必属精品).DataGrip整合集成了当前主流数据库(如:SQL Server, MySQL, ...
- 数据库 --> SQL Server 和 Oracle 以及 MySQL 区别
SQL Server 和 Oracle 以及 MySQL 区别 三者是目前市场占有率最高(依安装量而非收入)的关系数据库,而且很有代表性.排行第四的DB2(属IBM公司),与Oracle的定位和架构非 ...
- 【转】SQL Server、Oracle、MySQL和Vertica数据库常用函数对比
SQL Server.Oracle.MySQL和Vertica数据库常用函数对比 Vertica数据库是HP公司新收购的用于BI方面的数据库. 1. 绝对值 S:select abs(-1) valu ...
随机推荐
- OSG开发笔记(三十二):深入理解相机视口、制作支持与主视图同步变换旋转的相机HUD
前言 深入理解相机视口,摸索相机视口旋转功能,背景透明或者不透明. 本篇,实现了一个左下角旋转HUD且背景透明的相机视口. Demo HUD相机的坐标 ...
- 啃啃老菜:Spring IOC核心源码学习(一)
啃啃老菜:Spring IOC核心源码学习(一) 本文主要以spring ioc容器基本代码骨架为切入点,理解ioc容器的基本代码组件结构,各代码组件细节剖析将放在后面的学习文章里. 关于IOC容器 ...
- python下的多线程与多进程
多进程: 进程我们可以理解为是一个可以独立运行的程序单位,比如打开一个浏览器,这就开启了一个浏览器进程:打开一个文本编辑器,这就开启了一个文本编辑器进程.但一个进程中是可以同时处理很多事情的,比如在浏 ...
- 鸿蒙NEXT元服务:论如何免费快速上架作品
[引言]天下武功,唯快不破. 本文讨论如何免费且以最快速度上架自己的作品. 作者以自己从零开始到提交发布审核一共俩小时的操作流程分享给大家作参考. [1]立项选择 结论:元服务,单机,工具类(非游戏) ...
- 规范LR(1)语法分析表
前面已经实现了SLR语法分析表,但是可能会出现即使语法不是二义性文法,也存在移入/规约冲突 状态 i 包含项[A ->α ],当状态 i 出现在栈顶时,栈中的可行前缀时βα且在任何最后句型中a都 ...
- Go 内存管理
操作系统内存管理 操作系统管理内存的存储单元是页(page),在 linux 中一般是 4KB.而且,操作系统还会使用 虚拟内存 来管理内存,在用户程序中,我们看到的内存是不是真实的内存,而是虚拟内存 ...
- "一基双台三智" 中电金信智慧监督解决方案构筑国央企风控堡垒
近年来,国务院国资委先后下发<关于进一步排查中央企业融资性贸易业务风险的通知>.<关于规范中央企业贸易管理严禁各类虚假贸易的通知>等各类监管法规,并在2024年初中央企业工作会 ...
- 零售经营“新赛道” ——基于手机银行APP专区调研的客群精细化运营分析报告
随着银行业竞争的不断深入及新客户增量日渐"到顶",各家银行的客群竞争逐渐由"跑马圈地"进入"精耕细作"的新阶段,在客群精准化服务方面不断 ...
- 【前端】【探究】HTML - input类型为file时如何实现自定义文本以更好的美化
想到英语四级考了两次都没过,我觉得要多使用英文,所以本文使用英文书写. 本文讲述了遇到的问题,解决的思路,并讲述了解决方案,也许对你会有帮助. 目录 Problem description Solut ...
- Qt开源作品17-IP地址输入控件
一.前言 这个IP地址输入框控件,估计写烂了,网上随便一搜索,保证一大堆,估计也是因为这个控件太容易了,非常适合新手练手,一般的思路都是用4个qlineedit控件拼起来,然后每个输入框设置正则表达式 ...