文章概要:

本文在https://www.cnblogs.com/kingbase/p/15703611.html

一文的基础上总结了Kingbase ES中函数能支持的return语句,整体上兼容oracle的基础上,也和PG语法一样。

同时列举了sqlserevr表值函数和代码故障案例。

一,关于return语句

有5个return语句可以用来从KES函数中返回数据:

RETURN

--执行后退出函数,函数返回类型须是return void

**RETURN expression **

--执行后退出函数,并立刻返回expression的值给调用者

RETURN NEXT expression

--执行后不退出函数,需要立刻退出可以使用return。可以被用于返回标量和复合数据类型;对于复合类型,将返回一个完整的结果“表”

RETURN QUERY query

--执行后不退出函数,而是追加要返回的结果集query,继续执行后面的语句,需要立刻退出可以使用return,函数结束时才最终返回给调用者

RETURN QUERY EXECUTE command-string [ USING expression [, ... ] ]

--RETURN QUERY的变种可以执行指定的动态SQL,同时可以指定传入的参数

二,使用场景

使用场景问题:

return 此情况的函数和存储过程一样无返回值,但是保留函数的调用方式

return expression 只能获取一个值,可以是标量也可以一个复合数据

return next 可以用于标量和复合类型数据,一般结合着for循环使用(如果涉及返回多行数据的话)

return query 将查询到的一条结果追加到函数的结果集中,无需结合for循环获取结果集;

return query execute 是 return query 的变形,用于执行指定的动态sql;

当需要函数返回一个数据集时,使用RETURN NEXT或者RETURN QUERY向结果集追加结果。

三,简单示例

**1,return expression **

return expression 只能获取一个值,可以是标量也可以一个复合数据

CREATE OR REPLACE FUNCTION getValue
(pv1 int)
RETURNS int
AS
DECLARE
vv int;
BEGIN
vv = 10 + pv1 * 0.95;
RETURN vv;
END; --运行结果
getvalue
----------
20 (1 row)

**2,return **

return 此情况的函数和存储过程一样无返回值,但是保留函数的调用方式

需要声明函数为RETURNS void,return则用于提前退出函数

CREATE OR REPLACE FUNCTION getReturn(pv1 int)
RETURNS void
AS
BEGIN
if pv1 > 10 then
RAISE NOTICE '-----------> %',pv1;
else
return;
end if;
RAISE NOTICE '-----------> end';
END; --运行结果
test=# select getreturn(10);
test-# / getreturn
----------- (1 row) test=# select getreturn(11); --大于10
test-# /
NOTICE: -----------> 11
NOTICE: -----------> end getreturn
----------- (1 row)

**3,return next **

--声明函数是returns setof some_type(就是返回多行some_type数据的意思)时,需要结合for循环使用

--造一些数据
create table t1 (id int, name text);
insert into t1 values (10, 'tom');
insert into t1 values (20, 'kim');
insert into t1 values (30, 'mun');
--返回表的多行数据
create or replace function getallrow() returns setof t1 as
declare
oner t1%rowtype;
begin
for oner in select * from t1 where id > 0
loop
-- 此处可以执行一些其他语句
return next oner; -- 返回当前查询行
end loop;
return;
end; --测试结果:
test-# /
getallrow
------------
(10,tom)
(20,kim)
(30,mun)
(3 rows) --返回表的某列的多行数据
create or replace function getallrow1() returns setof text as
declare
onename text;
begin
for onename in select name from t1 where id > 0
loop
-- 此处可以执行一些其他语句
return next onename ; -- 返回当前查询行
end loop;
return;
end; test-# /
getallrow1
------------
tom
kim
mun
(3 rows) --返回表多列的多行数据
CREATE TYPE ttype AS (id int, name text); create or replace function getallrow2() returns setof ttype as
declare
onename record;
begin
for onename in select id,name from t1 where id > 0
loop
-- 此处可以执行一些其他语句
return next onename ; -- 返回当前查询行
end loop;
return;
end; test-# /
getallrow2
------------
(10,tom)
(20,kim)
(30,mun)
(3 rows)

4,RETURN QUERY query

执行后不退出函数,而是存入要返回的结果集query,继续执行后面的语句,需要立刻退出可以使用return,函数结束时才最终返回给调用者

4.1结合RETURNS SETOF使用

CREATE FUNCTION get_tid(int)
RETURNS SETOF integer
AS
BEGIN
RETURN QUERY SELECT id
FROM t1
WHERE id >= $1;
-- 因为执行还未结束,我们可以检查是否有行被返回
-- 如果没有就抛出异常。
if $1 < 0 then
RAISE EXCEPTION 'error number %.', $1;
end if;
RETURN; --可以使用return在return query之后退出函数
END; --运行结果
test=# select get_tid(10);
test-# /
get_tid
---------
10
20
30
(3 rows) test=# select get_tid(15);
test-# /
get_tid
---------
20
30
(2 rows) test=# select get_tid(-1);
test-# /
ERROR: error number -1.
CONTEXT: PL/SQL function get_tid(integer) line 9 at RAISE --也可以这样调用(和下面的return table结果有点区别)
test=# select * from get_tid(20);
test-# /
get_tid
---------
20
30
(2 rows)

4.2 结合RETURNS table,也是用来获取多行结果集的

CREATE FUNCTION get_tid2(int)
RETURNS table (num integer )
AS
BEGIN
RETURN QUERY SELECT id
FROM t1
WHERE id >= $1;
-- 因为执行还未结束,我们可以检查是否有行被返回
-- 如果没有就抛出异常。
if $1 < 0 then
RAISE EXCEPTION 'error number %.', $1;
end if;
RETURN; --可以使用return在return query之后退出函数
END; --运行结果 test=# select get_tid2(10)
test-# / get_tid2
----------
10
20
30 (3 rows) test=# select get_tid2(15)
test-# / get_tid2
----------
20
30 (2 rows) test=# select get_tid2(-1)
test-# /
ERROR: error number -1.
CONTEXT: PL/SQL function get_tid2(integer) line 9 at RAISE --也可以这样调用
test=# select * from get_tid2(20);
test-# /
num
-----
20
30
(2 rows)

5, RETURN QUERY EXECUTE

--RETURN QUERY的变种可以执行指定的动态SQL,同时可以指定传入的参数

依然基于4中的例子使用RETURN QUERY EXECUTE来等价改写,

注意:SQL 字符串中的$1 即是指第一个占位符,即使用USING子句传递的第一个值,

USING中的$1就是函数的第一个参数(两者恰好在各自的范围内都是 $1

create or replace function get_tid3(int)
returns table (num integer )
as
​ return query execute 'select id from t1 where id >= $1'
​ using $1;
​ -- 因为执行还未结束,我们可以检查是否有行被返回
​ -- 如果没有就抛出异常。
​ if $1 < 0 then
​ raise exception 'error number %.', $1;
​ end if;
​ return; --可以使用return在return query之后退出函数
end; test=# select* from get_tid3(5);
test$# / num
-----
10
20
30
(3 rows) test=# select* from get_tid3(20);
test$# /
num
-----
20
30
(2 rows) test=# select* from get_tid3(-1);
test$# /
ERROR: error number -1.
CONTEXT: PL/pgSQL function get_tid3(integer) line 8 at RAISE

四,SQLServer中的表值函数

Sql server 的表值函数是返回一个Table类型,table类型相当与一张存储在内存中的一张虚拟表。

create  function  tvpoints()
returns @points table (x float , y float )
as begin
insert @points values (1,2);
insert @points values (3,4);
return ;
end select * from tvpoints() --像查询表一样运行 --运行结果 x y
1 2
3 4

如何?其实作用就是KES中返回值为return query/return next的函数。上面的改写为KES中的语法形式就是:

create  function  tvpoints()
returns table (x float , y float )
as
begin
create temp table points(x float , y float);
insert into points values (1,2);
insert into points values (3,4);
return query select x,y from points;
end select * from tvpoints() test=# select * from tvpoints();
test$# /
x | y
---+---
1 | 2
3 | 4
(2 rows)

五,一个代码故障案例

这个是一个形成了死循环的代码故障案例,显然问题点在于循环里,RETURN query并会立刻退出函数。

CREATE OR REPLACE FUNCTION Get_StrTable("@content" text, "@length" integer)
RETURNS TABLE(id integer, content text)
AS
BEGIN
CREATE temp TABLE p_table
(
id serial,
content text
);
declare @allStrLen int= LEN(@content) ;
declare @lesStrLen int = LEN(@content) ;
declare @subStr_begin int=1 ;
declare @subStrLen int = @length ;
declare @subStrLen_before int = 0 ;
declare @subStr_before text ;
declare @subCONTENT text ; if isnull(@content,'')<>''
begin
while(@subStr_begin<=@allStrLen)
begin
select @subCONTENT = SUBSTRING(@content,@subStr_begin,@subStrLen);
if(@lesStrLen = LEN(@subCONTENT))
begin
insert into p_table(content) values(@subCONTENT);
RETURN query SELECT * FROM p_table; ---问题在这里,执行后并不会立刻退出函数
end
else if(datalength(@subCONTENT) <= @length*2-1)
begin
select @subStrLen = @subStrLen + 1;
end
else --截取字符长度达到目标长度
begin
insert into p_table(content) values(@subCONTENT) ;
select @subStrLen_before = @subStrLen_before + @subStrLen ;
select @subStr_before = SUBSTRING(@content,1,@subStrLen_before) ;
select @subStr_begin = @subStrLen_before+1;
select @subStrLen = @length ;
select @lesStrLen = @allStrLen - @subStrLen_before ;
END
end;
END;
RETURN query SELECT * FROM p_table;
END;

Kingbase ES 函数返回-return语句的更多相关文章

  1. exit函数和return语句

    exit函数是c语言的库函数,有一个整型的参数,代表进程终止,这个函数需<stdlib.h>头文件 在函数中写return只是代表函数终止了,不管在程序的任何位置调用exit那么进程就立即 ...

  2. python匿名函数以及return语句

  3. Python函数(一)-return返回值

    定义一个函数可以在最后加上return返回值,方便查看函数是否运行完成和返回函数的值 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR&qu ...

  4. Python 函数返回值

    本章详细介绍 返回值: 0x 00 返回值简介 0x 01 指定返回值与隐含返回值 0x 02 return 语句位置与多条 return 语句 0x 03 返回值类型 0x 04 函数嵌套 0x 0 ...

  5. C++中的break,continue和return语句小结

    1.break语句能用在switch,while,do...while和for语句中:continue语句用在while,do...while和for语句中. 2.break结束语句执行,并将程序的执 ...

  6. return语句的用法

    1.return语句的作用:a.返回一个值,这个值可以是任意类型.b.使程序返回到操作系统(即终止程序)2.java中对于一个函数,不论有没有返回值类型,都可以带有return 语句.但是区别在于,r ...

  7. Python 函数返回值、作用域

    函数返回值 多条return语句: def guess(x): if x > 3: return "> 3" else: return "<= 3&qu ...

  8. C语言的return语句

    Q1:函数中的Return语句有什么用? Q2:Return 0有什么含义吗? A1:Return的作用为,跳出当前的函数,并且返回到调用当前函数的主调函数,当前函数中Return语句一下代码将不会运 ...

  9. 函数----基础,参数传递,返回类型和return语句

    一.函数基础1.形参和实参 实参是形参的初始值.第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推.尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序.编译器能以任意可行的顺序对实 ...

  10. Python return语句 函数返回值

    return语句是从python 函数返回一个值,在讲到定义函数的时候有讲过,每个函数都要有一个返回值.Python中的return语句有什么作用,今天就来仔细的讲解一下. python 函数返回值 ...

随机推荐

  1. 使用JS保存数据

    1 保存到text中 demo1.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...

  2. Java I/O 教程(四) FileInputStream 类

    Java FileInputStream class 从一个文件读取字节数据. 用于从图像,音频,视频等文件中读取字节类型数据. 类定义 public class FileInputStream ex ...

  3. win32-制作mini dump文件

    一个完整的用户模式dump是基本的用户模式转储文件. 此转储文件包括进程的整个内存空间,程序的可执行映像本身,句柄表以及其他信息,这些信息对于调试器在重建转储发生时正在使用的内存中很有用. 可以将完整 ...

  4. 使用`react-hooks写法`对`antd的Upload.Dragger上传组件`进行二次封装

    使用react-hooks写法对antd的Upload.Dragger上传组件进行二次封装 预期 对antd的Upload.Dragger组件进行二次封装,让它的使用方法和Upload.Dragger ...

  5. 详解SSL证书系列(1)什么是SSL证书?

    你一定遇到过这种情况,打开一个网站,浏览器弹出警告"您与此网站之间建立的连接不安全.由于此连接不安全,因此信息(如密码或信用卡)不会安全地发送到此网站,并且可能被其他人截获或看到" ...

  6. python开发接口时,使用jsonschema模块对数据进行校验

    import jsonschema schema = { "type": "object", # 先声明每个键都是对象 "properties&quo ...

  7. 【Azure 服务总线】如何批量删除Azure Service Bus中的Topics(数量较多,需要过滤后批量删除)

    问题描述 Azure Service Bus 的门户操作页面上,是否可以批量删除其中的Topics呢? 问题解答 Azure Service Bus门户或Service Bus Explorer工具没 ...

  8. 【Azure 环境】通过Python SDK收集所有订阅简略信息,例如订阅id 名称, 资源组及组内资源信息等,如何给Python应用赋予相应的权限才能获取到信息呢?

    问题描述 通过Python  SDK收集所有订阅简略信息,例如订阅id 名称, 资源组及组内资源信息等,如何给Python应用赋予相应的权限才能获取到信息呢?在一个企业的账号中,同一个组织有一个相同的 ...

  9. Java11改进的垃圾回收器

    传统的C/C++等编程语言,需要程序员负责回收已经分配的内存.显示进行垃圾回收是一件比较困难的事情,因为程序员并不总是知道内存应该何时被释放.如果一些分配出去的内存得不及时回收,就会引起系统运行速度下 ...

  10. Redis单线程为什么如此之快

    一.概述 Redis的高并发和快简单可以归结为一下几点: 1.Redis是基于内存的: 2.Redis是单线程的: 3.Redis使用多路复用技术. 4.高效的数据结构 但具体怎么做的呢,下面来详细看 ...