Db2 SQL PL的锚点类型和行数据类型

环境

  • 操作系统:Ubuntu 20.04
  • Db2:11.5.0.0

锚点数据类型

锚点类型是基于另一个数据库对象而定义的类型,比如列、全局变量、SQL变量等。

锚点变量与普通变量的区别在于,前者将会引用到某个具体的东西上。从这个角度看,我感觉锚点类型有点类似于“外键”的概念。

创建表 tab1tab2 如下:

CREATE TABLE tab1(col1 INT, col2 CHAR)

INSERT INTO tab1 VALUES (1,2)

INSERT INTO tab1 VALUES (3,4)

CREATE TABLE tab2 (col1a INT, col2a CHAR)

创建文件 test1.sql 如下:

CREATE OR REPLACE PROCEDURE p1()
BEGIN
  DECLARE var1 ANCHOR tab1.col1;

  SELECT col1 INTO var1 FROM tab1 WHERE col2 = 2;

  INSERT INTO tab2 VALUES (var1, 'a');
END@

CALL p1()@

运行脚本 test1.sql ,如下:

➜  temp0527 db2 -td@ -f test1.sql
DB20000I  The SQL command completed successfully.

  Return Status = 0

查看表 tab2 ,可见多了一行记录:

➜  temp0527 db2 "select * from tab2"

COL1A       COL2A
----------- -----
          1 a    

  1 record(s) selected.

本例中,锚点变量 var1 定义为引用 tab1 表的 col1 列,接下来赋值为特定行的 col1 列的值,最后就可以像一般变量一样使用 var1

注意,给 var1 赋值时,可以没有满足条件的值,但不能有多个满足条件的值。

  • 如果 SELECT col1 FROM tab1 WHERE col2 = 2 结果为空,则 var1 的值为 NULL ,没有问题(这一点也与外键一致,外键的值可以为空,即不引用任何具体值);
  • 如果 SELECT col1 FROM tab1 WHERE col2 = 2 结果有多个值,则会报错;

创建 test2.sql 文件如下:

CREATE OR REPLACE PROCEDURE p2(in var1 anchor tab1.col1)
BEGIN
  INSERT INTO tab2 VALUES (var1, 'b');
END@

CALL p2(100)@

运行 test2.sql 脚本,如下:

➜  temp0527 db2 -td@ -f test2.sql
DB20000I  The SQL command completed successfully.

  Return Status = 0

结果有点出乎意料, 100 并不是 tab1 表的 col1 字段的值,但是也没报错, tab2 里插入了一条 (100, 'b') 的记录。既然这样,那声明为 anchor tab1.col1 又有什么用呢?

行数据类型

行变量,顾名思义,就是代表了一行记录。

要使用行变量,就要先创建行数据类型,比如:

create or replace type myrow as row(c1 int, c2 varchar(100))

然后就可以声明行变量了,比如:

declare r1 myrow

创建行变量时,其中的每个字段会初始化为 NULL 值。

可将下列类型的值指定给行变量:

  • literal
set r1 = (1, 'aaa')
  • 表达式
values (1, 'aaa') into r1
  • 函数返回值
set r1 = f1()
  • 其它变量
set r1 = r2

注意: r1r2 必须是相同或兼容类型。如果 r1r2 是完全不同的数据类型 myrow1myrow2 ,即使 myrow1myrow2 定义一样,也不能通过 set r1 = r2 来赋值,因为二者类型不兼容。

  • 查询结果
set r1 = (select c1, c2 from t1)

注意:必须是0行或单行结果。

  • NULL

注意:各个字段设置为 NULL ,但行变量本身并不为 NULL

行变量赋值方式:

  • set

参见前面例子。

  • values into

参见前面例子。

  • select into
select 1, 'aaa' into r1 from sysibm.sysdummy1
  • fetch into
declare c1 cursor for select 1, 'aaa' from sysibm.sysdummy1;

open c1;

fetch c1 into r1;

close c1;

对行变量的字段(即 <行变量>.<列> )赋值的类型和方式和对行变量赋值的类型和方式类似。

不能直接比较两个行变量,只能其比较其字段值。

可以在insert语句中使用行变量,比如:

insert into t1 values r1

等价于:

insert into t1 values (r1.c1, r1.c2)

可以在一个insert语句中插入多个行变量:

insert into t1 values r1, r2

下面看一个完整例子。

创建文件 test3.sql 如下:

create or replace type myrow as row(c1 int, c2 varchar(100))@

set serveroutput on@

begin
	declare r1, r2 myrow;

	declare c1 cursor for select 3, 'ccc' from sysibm.sysdummy1;

	set r1 = (1, 'aaa');

	call dbms_output.put_line('1)' || r1.c1 || ', ' || r1.c2);

	set r2 = r1;

	call dbms_output.put_line('2)' || r2.c1 || ', ' || r2.c2);

	set r1 = null;

	call dbms_output.put_line('3)' || coalesce(cast(r1.c1 as varchar(100)), '') || ', ' || coalesce(r1.c2, ''));

	select 2, 'bbb' into r1 from sysibm.sysdummy1;

	call dbms_output.put_line('4)' || r1.c1 || ', ' || r1.c2);

	open c1;

	fetch c1 into r1;

	close c1;

	call dbms_output.put_line('5)' || r1.c1 || ', ' || r1.c2);
end@

set serveroutput off@

drop type myrow@

运行脚本 test3.sql ,如下:

➜ temp0527 db2 -td@ -f test3.sql 
DB20000I  The SQL command completed successfully.

DB20000I  The SET SERVEROUTPUT command completed successfully.

DB20000I  The SQL command completed successfully.

1)1, aaa
2)1, aaa
3), 
4)2, bbb
5)3, ccc

DB20000I  The SET SERVEROUTPUT command completed successfully.

DB20000I  The SQL command completed successfully.

注:在 3) 处,由于 NULL 和其他字符串拼接以后还是 NULL ,所以这里使用 coalesce() 函数将 NULL 转为 '' ,但是 int 类型的 NULL'' 不兼容,所以先强制转换为 varchar 类型,然后再使用 coalesce() 函数。

参考

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值