IT评测·应用市场-qidao123.com技术社区

标题: 浅谈DWS函数出参方式 [打印本页]

作者: 勿忘初心做自己    时间: 2023-3-17 16:37
标题: 浅谈DWS函数出参方式
摘要:DWS的PL/pgSQL函数/存储过程中有一个特殊的语法PERFORM语法,用于执行语句但是丢弃执行结果的场景,常用于一些状态判断的场景。
本文分享自华为云社区《GassDB(DWS)功能 -- 函数出参 #【玩转PB级数仓GaussDB(DWS)】》,作者:譡里个檔。
DWS的PL/pgSQL函数/存储过程中有一个特殊的语法PERFORM语法,用于执行语句但是丢弃执行结果的场景,常用于一些状态判断的场景。但是客户往往会不当使用PERFORM语法,导致业务逻辑出错,最常见的就是使用PERFORM执行带有出参的函数。
已知函数inner定义如下
  1. CREATE OR REPLACE FUNCTION public.inner(
  2.     IN a1 integer,
  3.     IN b1 integer,
  4.     OUT a integer,
  5.     OUT b integer
  6. )
  7. RETURNS record
  8. LANGUAGE plpgsql
  9. NOT FENCED NOT SHIPPABLE
  10. AS $function$
  11. DECLARE
  12. BEGIN
  13. a := a1;
  14. b := b1;
  15. END$function$
  16. ;
复制代码
函数f_outer定义如下,函数体中调用函数inner,把函数的出参赋值给变量a, b
  1. CREATE OR REPLACE FUNCTION public.f_outer(IN i_a int, IN i_b int)
  2. RETURNS void
  3. LANGUAGE plpgsql
  4. NOT FENCED NOT SHIPPABLE
  5. AS $function$
  6. DECLARE
  7. a int;
  8.     b int;
  9. BEGIN
  10.     PERFORM public.inner(i_a, i_b, a, b);
  11.     RAISE INFO 'a = %, b = %', a, b;
  12. END$function$
  13. ;
复制代码
但是实际执行的时候发现函数inner的出参没有正确赋值(预期值为a = 1 b = 11)。
  1. postgres=# CALL f_outer(1, 11);
  2. INFO:  a = <NULL>, b = <NULL>
  3. SQLSTATE: 00000
  4. f_outer
  5. ---------
  6. (1 row)
  7. Time: 1.086 ms
复制代码
出现这种问题的原因是PERFORM语法会执行SQL语句,但是会抛弃执行结果,导致函数出参没有赋值
DWS中常用的带出函数出参的方式有以下三种:
  1. CREATE OR REPLACE FUNCTION public.test1(IN i_a int, IN i_b int)
  2. RETURNS void
  3. LANGUAGE plpgsql
  4. NOT FENCED NOT SHIPPABLE
  5. AS $function$
  6. DECLARE
  7. a int;
  8.     b int;
  9. BEGIN
  10. public.inner(i_a, i_b, a, b);
  11.     RAISE info 'a = %, b = %', a, b;
  12. END$function$
  13. ;
复制代码
  1. CREATE OR REPLACE FUNCTION public.test2(IN i_a int, IN i_b int)
  2. RETURNS void
  3. LANGUAGE plpgsql
  4. NOT FENCED NOT SHIPPABLE
  5. AS $function$
  6. DECLARE
  7. a int;
  8.     b int;
  9. BEGIN
  10. EXECUTE IMMEDIATE 'SELECT * from public.inner(:1, :2)' UNSING INTO a, b USING IN i_a, i_b;
  11.     RAISE INFO 'a = %, b = %', a, b;
  12. END$function$
  13. ;
复制代码
  1. CREATE OR REPLACE FUNCTION public.test3(IN i_a int, IN i_b int)
  2. RETURNS void
  3. LANGUAGE plpgsql
  4. NOT FENCED NOT SHIPPABLE
  5. AS $function$
  6. DECLARE
  7. a int := 0;
  8.     b int := 0;
  9. BEGIN
  10. SELECT * INTO a, b FROM public.inner(i_a, i_b);
  11.     RAISE INFO 'a = %, b = %', a, b;
  12. END$function$
  13. ;
复制代码
 
点击关注,第一时间了解华为云新鲜技术~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4