首页 > 其他分享 >Kingbase ES 函数返回-return语句

Kingbase ES 函数返回-return语句

时间:2023-09-18 16:22:07浏览次数:44  
标签:return get -- Kingbase select test RETURN ES

文章概要:

本文在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;

标签:return,get,--,Kingbase,select,test,RETURN,ES
From: https://www.cnblogs.com/kingbase/p/17561083.html

相关文章

  • kingbaseES V8R3集群运维案例之---集群部署前后ssh端口修改
    kingbaseESV8R3集群运维案例之---集群部署前后ssh端口修改案例说明:kingbaseESV8R3集群部署读写分离的集群是使用ssh的默认端口(22)部署,当改为非默认端口时,在部署中或部署后会因kingbasecluster脚本ssh的连接而失败,现提出以下解决方案。适用版本:KingbaseESV8R31......
  • 使用MessageFormatter.format替代 String.format
    使用MessageFormatter.format替代String.format现有的J2EE项目中基本都会引用日志框架,刚好日志框架中有对应的工具类可以使用,对数据进行格式化:importorg.slf4j.helpers.MessageFormatter;Stringformat1=String.format("%s/%s",1,2);S......
  • presto/trino QueryStatistics 数据来源分析
    QueryStatisticsQueryStats来自stageStats累加来自taskStats累加PipelineStatsdriverStatsOperatorStatsinputOperatorPageSourceOperatorTableScanOperatorWorkProcessorPipelineSourceOperatorWorkProcessorSourceOperatorAdapter......
  • KingbaseES V8R6运维案例之---数据库resetwal后启动失败
    KingbaseESV8R6运维案例之---数据库resetwal后启动失败案例说明:KingbaseESV8R6集群触发failover切换后,原主库自动recovery失败,现在需要将原主库启动为单实例的数据库运行,在执行了resetwal后,启动数据库失败。sys_log记录以下故障信息:适用版本:KingbaseESV8R6......
  • KingbaseES V8R6集群运维案例之---访问系统表unrecognized token- false故障
    KingbaseESV8R6集群运维案例之---访问系统表‘unrecognizedtoken:"false"’故障案例说明:KingbaseESV8R6集群在升级补丁后,主备库访问系统表出现‘unrecognizedtoken:"false"’故障,如下图所示:适用版本:KingbaseESV8R3/R6一、问题分析1、连接数据库执行系统表访问(如......
  • KingbaseES V8R6集群运维案例--cluster模式备份sys_backup.sh init故障
    KingbaseESV8R6集群运维案例--cluster模式备份sys_backup.shinit故障案例说明:通过脚本方式部署KingbaseESV8R6集群后,在‘cluster’模式备份,执行sys_backup.shinit时,出现“cannotcontain//for”log-path"option"错误,但是在‘single’模式下备份,无此错误。故障信息......
  • KingbaseES V8R6集群运维案例之---修改ssh端口后脚本创建互信
    案例分析:在KingbaseESV8R6集群部署时,需要建立节点之间ssh互信(或者使用securecmdd工具),在有的生产环境,为了安全起见会修改ssh的默认端口;KingbaseESV8R6集群部署提供了脚本用于创建ssh互信,如果修改了系统的ssh端口号后,也需要修改对应的脚本。适用版本:KingbaseESV8R6一、集群节......
  • RestTemplate【Spring 提供的用于访问Rest 服务的模板类】
    RestTemplate基本介绍RestTemplate是Spring提供的用于访问Rest服务的模板类RestTemplate提供了多种便捷访问远程Http服务的方法老韩说明:小伙伴可以这样理解,通过RestTemplate,我们可以发出http请求(支持Restful风格),去调用Controller提供的API接口,就像我们使......
  • pytest的Hook函数之pytest.hookimpl(hookwrapper=True):获取测试用例结果
    装饰器@pytest.hookimpl(hookwrapper=True),它的作用和装饰器@pytest.mark.hookwrapper是一样的@pytest.hookimpl(hookwrapper=True)装饰的钩子函数,有以下两个作用:(1)可以获取到测试用例不同执行阶段的结果(setup,call,teardown)(2)可以获取钩子方法的调用结果(yield返回一个result对象)和调......
  • DVWA靶场通关-Weak Session IDs(弱会话IDs)
    当用户登录后,在服务器就会创建一个会话(session),叫做会话控制,接着访问页面的时候就不用登录,只需要携带Sesion去访问。Session利用的实质:由于SessionID是用户登录之后才持有的唯一认证凭证,因此黑客不需要再攻击登陆过程(比如密码),就可以轻易获取访问权限,无需登录密码直接进入特......