plsql select into 赋值异常问题详解

问题1:报错:未找到任何数据

错误截图:
在这里插入图片描述

基础数据准备:

declare
  v_dname scott.dept.dname%type;
begin
  select t.dname
    into v_dname 
    from scott.dept t 
   where t.deptno = 50; -- 不存在 deptno=50 的记录
   
  dbms_output.put_line(v_dname);
end;

在这里插入图片描述

原因分析

未找到任何数据:不存在 deptno = 50 的记录

解决办法

解决办法1:使用 “聚合函数”(简单、粗暴,但要 ‘心中有数’)

declare
  v_dname scott.dept.dname%type;
begin
  select MAX(t.dname) -- 记录不存在时,为空
    into v_dname 
    from scott.dept t 
   where t.deptno = 50; -- 不存在 deptno=50 的记录
   
  dbms_output.put_line(v_dname); -- 输出空
end;

解决办法2:捕获异常(所以在写该语句时,要特别留意!)

declare
  v_dname scott.dept.dname%type;
begin
  select t.dname
    into v_dname 
    from scott.dept t 
   where t.deptno = 50; -- 不存在 deptno=50 的记录
   
  dbms_output.put_line(v_dname);
exception 
   when others then 
     dbms_output.put_line(sqlerrm);
     dbms_output.put_line(dbms_utility.format_error_backtrace);
end;

问题2:数据同步前后数据不匹配

图示:source_table、source_table2 以 sno 相同的记录同步至 tartget_table
在这里插入图片描述

基础数据准备:

create table scott.source_table (
   sno   number(10),
   sname varchar2(50)
);

create table scott.source_table2 (
   sno     number(10),
   address varchar2(50)
);

create table scott.target_table (
   sno     number(10),
   sname   varchar2(50),
   address varchar2(50)
);

insert into scott.source_table(sno, sname) values(1, '瑶瑶');
insert into scott.source_table(sno, sname) values(2, '优优');
insert into scott.source_table(sno, sname) values(3, '倩倩');
insert into scott.source_table(sno, sname) values(4, '朝爷');
insert into scott.source_table(sno, sname) values(5, '姥姥');

insert into scott.source_table2(sno, address) values(1, '赤壁');
insert into scott.source_table2(sno, address) values(3, '牌洲');
insert into scott.source_table2(sno, address) values(4, '嘉鱼');
commit;

同步数据脚本:(简易版)

--************************************************************************
-- 功能说明:把表 scott.source_table、scott.source_table2 中的数据 
--          同步至表 scott.target_table
-- 备注   : 简化程序,仅为说明现象
--************************************************************************
declare
   v_address scott.source_table2.address%type;
   v_count   number(1);
begin
   for i in (select st.sno, st.sname from scott.source_table st) loop
   
      select count(1)
        into v_count
        from scott.source_table2 st2
       where st2.sno = i.sno;
   
      -- 变量赋值,报错点!(报错场景:当 v_count = 0 时)
      if v_count >= 1 then
         select st2.address
           into v_address
           from scott.source_table2 st2
          where st2.sno = i.sno;
      end if;
   
      -- 插入 "目标表"
      insert into scott.target_table
         (sno, sname, address)
      values
         (i.sno, i.sname, v_address);
   end loop;

   -- 最后提交数据
   commit;
end;

原因分析

1. 当 sno = 1 时,能够查询到 address = '赤壁',此时 v_address = '赤壁'
2. 当 sno = 2 时,查询不到 address,此时 v_address 还是 '赤壁''并未初始化')
   所以,问题出来了!

解决办法

解决办法1:在给 v_address 赋值之前,先初始化 v_address

-- 解决办法:在给 v_address 赋值之前,先初始化 v_address
v_address = '';

if v_count >= 1 then
   select st2.address
     into v_address
     from scott.source_table2 st2
    where st2.sno = i.sno;
end if;

解决方法2(推荐):使用关联查询,避免 select into 的赋值形式

-- 先清空 "目标表",以免影响测试
truncate table scott.target_table;

-- 使用关联查询,如:for 循环中
declare
   v_address scott.source_table2.address%type;
begin
   for i in (select st.sno,
                    st.sname,
                    (select st2.address
                       from scott.source_table2 st2
                      where st2.sno = st.sno) address
               from scott.source_table st) loop
   
      -- 插入 "目标表"
      insert into scott.target_table
         (sno, sname, address)
      values
         (i.sno, i.sname, i.address);
   end loop;

   commit;
end;
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼丸丶粗面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值