返回顶部
首页 > 资讯 > 数据库 >oracle存储过程转达梦8存储过程时踩过的坑
  • 160
分享到

oracle存储过程转达梦8存储过程时踩过的坑

oracle存储过程转达梦8存储过程时踩过的坑 2021-04-19 08:04:14 160人浏览 才女
摘要

达梦存储过程的语法与oracle的高度相似,但有好多细节还是有差异。我在这次项目迁移中踩过不少小坑,在这里给大家分享一下。 说明一下,我用的版本是达梦8,迁移时碰到的问题有些我已经反馈给达梦的官方群管理员,估计以后会有修复。 rp

oracle存储过程转达梦8存储过程时踩过的坑

达梦存储过程的语法与oracle的高度相似,但有好多细节还是有差异。我在这次项目迁移中踩过不少小坑,在这里给大家分享一下。

说明一下,我用的版本是达梦8,迁移时碰到的问题有些我已经反馈给达梦的官方群管理员,估计以后会有修复。

rpad问题

达梦的rpad函数,计算中文时永远是认为一个中文字符中两个字节,即使数据库设置的字符集是utf8(目前就发现rpad/lpad函数有这个问题,其它字符串函数都能正确识别,当字符集是utf8时能识别出来一个字符中3个字节)

测试代码:

select rpad("我是hch", 6), lengthb("我是hch") from dual -- 达梦输出"我是hc 9"
uNIOn all
select rpad("我是hch", 5), length("我是hch") from dual -- 达梦输出"我是h 5" 
union all
select rpad("我是hch", 3), length("我是hch") from dual; -- 达梦输出"我 5"

这个问题达梦的工作人员说以后会修复,目前我的解决方法是自己写一个rpad函数

 function rpad_dm(string varchar2, padded_length number, pad_string varchar2 := " ")
    return varchar2 IS
    v_len number := lengthb(string);
  BEGIN
  	    dbms_output.put_line("v_len - padded_length = " );
  	if padded_length < v_len THEN
  		return substrb(string, 1, padded_length); --如果输入长度小于原字符串长度,则调用substrb截断
  	elsif padded_length = v_len THEN
  		return string; --如果长度相等直接返回原串即可
  	else
  		return string || rpad(" ", padded_length - v_len, pad_string); --如果长度大于原字符串,则在后面补空格
  	end if;
  END;

短路问题

一般编程语言都会提供短路功能,在计算与或逻辑时,如果前半段逻辑已经能确定真假时,后半段逻辑不会执行。

plsql里面也实现了短路功能,我们一般会利用这个特性减少一些代码,例如先判断变量是否为空,如果不为空再使用变量做运算:

if (var is not null and va.exists("error") ) then dbms_output.put_line("yes"); fi;

但在达梦的存储过程,短路却没有实现。上面的代码不管var是否为空,都会进行va.exists("error")这个逻辑。如果不幸var的变量是空的,就会导致运行异常。

测试代码1:

dbms_output.enable;
declare
  v_flag boolean;
begin
  -- 请问这个存储过程执行异常,报"非法的参数数据"  是不是达梦的bug oracle下是可以正常运行的
  -- 还是有什么设置可以让存储过程正常执行
  if  (to_number("1") != 1) and to_number("abc") = 1 then
    dbms_output.put_line("yes");
  end if;
  dbms_output.put_line("ok");
end;

测试代码2:

dbms_output.enable;
declare
       TYPE TEST_RPT_LIST IS TABLE OF number INDEX BY PLS_INTEGER;
       o_demo_list TEST_RPT_LIST;
       i_report_id number := 17410491;
BEGIN
  -- 验证达梦8 if短路
  select 1 BULK COLLECT INTO o_demo_list from dual;
  dbms_output.put_line("o_demo_list(1) = " || o_demo_list(1));


  if o_demo_list(1) = 1 or o_demo_list(2) = 2 THEN -- or 短路没问题
  	dbms_output.put_line("or yes"); -- or yes能正常输出
  end if;

  if o_demo_list(1) != 1 and o_demo_list(2) = 2 THEN -- o_demo_list(1) != 1 不成立  为什么还要执行o_demo_list(2) = 2判断
    dbms_output.put_line("and yes"); -- 这里永远不应该输出
  end if;

  dbms_output.put_line("done"); -- 走不到done
EXCEPTION
  WHEN no_data_found THEN
     dbms_output.put_line("no_data_found tbl_demo_tab " || "ID " || to_char(i_report_id));
  WHEN OTHERS THEN
    -- RaiSE;
    dbms_output.put_line("err:" || sqlcode || sqlerrm);
END;

不只是if有短路问题,decode,case when等类似的都会有短路问题。

"case 判断 when 表达式1 else 表达式2 end" 在oracle是如果条件成立则执行条件1并返回其值,而在达梦是同时执行表达式1和表达式2,并根据判断结果返回一个值。

解决方法是不要偷懒,不依赖短路实现,多写几个if判断,或者把decode拆成多个if else语句。

深浅拷贝问题

oracle的table数组变量的赋值,默认是值复制(即深拷贝),而达梦默认是引用复制(即浅拷贝)。

也就是说在oracle使用 tmpArr := arr (tmpArr 和arr 都是数组),然后对这个tmpArr操作,不会影响arr的值,而在达梦,修改tmpArr数组元素的内容就是在修改arr

测试代码

        FOR vv IN 1 .. 5 -- crontab 初始化赋值
        LOOP                
                CASE vv
                WHEN 1 THEN
                        v_obj.minutes := tmpArr;
                WHEN 2 THEN
                        v_obj.hours := tmpArr;
                WHEN 3 THEN
                        v_obj.days := tmpArr;
                WHEN 4 THEN
                        v_obj.months := tmpArr;
                WHEN 5 THEN
                        v_obj.weeks := tmpArr;
                END CASE;
        END LOOP;

在oracle对v_obj这样赋值后,v_obj.minutes和v_obj.hours是两个不同的变量,分别对两个变量修改,相互之间不会出现干扰。而在达梦8,v_obj下面所有变量都指向同一个数组,对v_obj任意一个成员修改,都会同时影响其它成员的值。

解决方法是自己写一个数组拷贝函数,例如这样:

function copy1kList(v_input t_str_list) return t_str_list IS
    v_tmplist t_str_list;
    v_ind PLS_INTEGER;
  begin
    --TYPE t_str_list  IS TABLE OF VARCHAR2(1024) INDEX BY PLS_INTEGER;
  	if v_input.count > 0 then
  		
  		v_ind = v_input.first;
  		while v_ind is not null
  		loop
  			v_tmplist(v_ind) := v_input(v_ind);
  			v_ind = v_input.next(v_ind);
  		end loop;
  	end if;
  	return v_tmplist;
  end;

使用这个函数代替数组变量赋值就能维持代码行为与oracle一致。

今天暂时先分享这三个问题,后面有时间再整理其它坑。这些坑比较隐蔽,花了我不少时间调试才发现,我把它们总结出来,希望能对你有所帮助。

您可能感兴趣的文档:

--结束END--

本文标题: oracle存储过程转达梦8存储过程时踩过的坑

本文链接: https://lsjlt.com/news/7511.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • oracle存储过程转达梦8存储过程时踩过的坑
    达梦存储过程的语法与oracle的高度相似,但有好多细节还是有差异。我在这次项目迁移中踩过不少小坑,在这里给大家分享一下。 说明一下,我用的版本是达梦8,迁移时碰到的问题有些我已经反馈给达梦的官方群管理员,估计以后会有修复。 rp...
    99+
    2021-04-19
    oracle存储过程转达梦8存储过程时踩过的坑
  • oracle存储过程迁移达梦心得
    这几天把项目的存储过程从oracle迁移到了达梦8,记录一下心得。国产数据库做到这样,已经算很了不起了,跟oracle兼容性确实很高。 但还是有一些细节没做好,主要是出错提示不友好,另外一个网上的资料也很少,出问题不好定位。(达梦...
    99+
    2017-10-08
    oracle存储过程迁移达梦心得
  • 8、MySLQ存储过程
    简述存储过程是SQL语句和控制流语句的语句串(语句集合)。它不仅可以带有输入参数还可以带有输出参数,存储过程是能够通过介绍参数向调用者返回结果集,结果集的格式由调用者确定。返回状态值给调用者,指明调用是成功...
    99+
    2024-04-02
  • oracle存储过程
    存储过程1、创建create procedure 过程名(变量名 in 变量类型...变量名 out 变量类型...)is//定义变量  注:变量类型后不需要指定大小begin//执行的语句end...
    99+
    2024-04-02
  • MySQL存储过程详解 mysql 存储过程
    mysql存储过程详解 1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Proce...
    99+
    2024-04-02
  • 存储过程
    存储过程是数据库对象之一,存储过程可以理解成数据库的子程序,在客户端和服务器端可以直接调用它。触发器是与表直接关联的特殊的存储过程,是在对表记录进行操作时触发的。 存储过程放在字典里,可以在不同用户和应用程序之间共享,并可以实现程...
    99+
    2015-02-05
    存储过程
  • Oracle万能存储过程
     create or replace procedure proc_data_check is    --定义变量    V_...
    99+
    2024-04-02
  • Postgresql 存储过程
    1、没有定义 plpsql createlang -d tms plpgsql 2、找出不连续的SN DROP FUNCTION IF EXISTS sn_miss(IN order_name TEXT, IN pcline TE...
    99+
    2021-03-04
    Postgresql 存储过程
  • MySQL 存储过程
    参考地址1:https://blog.csdn.net/yanluandai1985/article/details/83656374 参考地址2:https://www.runoob.com/w3cnote/mysql-stored-p...
    99+
    2016-08-26
    MySQL 存储过程
  • mysql存储过程
      -- 创建清除过期积分存储过程DELIMITER //DROP PROCEDURE IF EXISTS reportUrl // CREATE PROCEDURE reportUrl() BEGIN -- 定义变量 ...
    99+
    2019-07-21
    mysql存储过程
  • plsql储存过程
    第九章  存储过程   初识存储过程   存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字并给出...
    99+
    2015-05-06
    plsql储存过程
  • MYSQL——存储过程
       MYSQL的存储过程 1   存储过程是SQL语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理2   存储过程的优点  &nbs...
    99+
    2024-04-02
  • MySQL--存储过程
    定义 一个复杂逻辑对SQL语句的批量处理, 通过一个名字存储 创建 delimiter // 修改终止符 -- 存储过程没有返回值 delimiter // ...
    99+
    2024-04-02
  • Oracle存储过程新手入门教程(通俗理解存储过程)
    目录一、存储过程通俗理解二、创建存储过程基本语法(汇总)三、执行存储过程的方式(5种)四、网上现有的创建存储过程的两种方式解释(看注释)五、一些存储过程示例(仅供参考)六、其他语法七...
    99+
    2023-03-03
    oracle如何创建存储过程 oracle数据库存储过程调用 oracle的存储过程写法
  • mysql的存储过程
    什么是存储过程 一组可编程的函数,是为了完成特定功能的SQL语句集 经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。 存储过程就是具有名字的一段代码,用来完成一个特定的功能。 创建的存储过...
    99+
    2015-04-21
    mysql的存储过程
  • Oracle数据库存储过程的调试过程
    目录oracle存储过程调试方法Oracle 存储过程的调试总结oracle存储过程调试方法 PL/SQL中为我们提供了【调试存储过程】的功能,可以帮助你完成存储过程的预编译与测试。 点击要调试的存储过程,右键...
    99+
    2022-07-05
    oracle 调试存储过程 oracle 存储过程怎么调试 oracle存储过程如何调试
  • 定时执行存储过程
    定时执行存储过程基础Oracle定时器Oracle定时器:定时执行某个存储过程。通过pl/SQL的图形化界面可以看到。定时器包括:调度和存储过程连接口 存储过程连接口存储过程连接口,主要告诉定时器...
    99+
    2024-04-02
  • 存储过程和函数 oracle
    declare begin   dbms_output.put_line("Hello World"); end; declare   i number := 10; begin   if i > 5 then     dbms_ou...
    99+
    2021-01-19
    存储过程和函数 oracle
  • mybatis调用oracle存储过程
    有输入与输出参数的存储过程oracle存储过程部分代码:create or replace procedure PT_copy_Shipment_One_Data(  oldShipmentId ...
    99+
    2024-04-02
  • Oracle存储过程和函数
      创建一个存储过程:CREATE OR REPLACE procedure proc_trade(    v_tradeid...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作