概要描述
上结论:
function 的 select sql 调用下,是不支持 function 内容中有“标准sql”和“set_env”这两个东西的。
详细说明
1、function中包含标准sql
function DDL:
create or replace function test_sql()
RETURN date
IS
v1 DATE;
BEGIN
select sysdate into v1 from system.dual;
RETURN v1
END
pl/sql调用下,正常:
DECLARE
v_date DATE;
BEGIN
v_date:=test_sql()
dbms_output.put_line(v_date)
END

注意:pl/sql下也是禁止sql调用包含标准sql的function的,至于需要sql调用带sql的plsql的情况,业务上建议在存储过程里面做关联查询或者嵌套子查询的方式。或者可以考虑如下的方式workaround(多值的话需要上游标):

普通sql调用下,异常:
SQL 错误 [30028] [42000]: COMPILE FAILED: Semantic error: [Error 30028] Line 1:7 PLSQL function is running in a non-driver environment, usually in SQL statement which doesn’t allow nested SQL statement. Error encountered near token ‘test_sql’
SELECT test_sql() FROM system.dual;

2、function 中包含 set_env
function DDL:
create or replace function test_set(v1 STRING,v2 STRING)
RETURN STRING
IS
BEGIN
set_env('plsql.catch.hive.exception',TRUE);
RETURN 'A'
END
pl/sql调用下,正常:
DECLARE
v1 STRING;
v2 STRING;
v_out STRING;
BEGIN
SELECT ENAME,JOB INTO v1,v2 FROM EMP_TORC WHERE ENAME='JONES'
v_out:=test_set(v1,v2)
dbms_output.put_line(v_out)
END

普通sql调用下,异常:
SQL 错误 [1] [08S01]: EXECUTION FAILED: Task MAPRED-SPARK error SparkException: [Error 1] Job aborted due to stage failure: Task 0 in stage 99.0 failed 4 times, most recent failure: Lost task 0.3 in stage 99.0 (TID 49, 172.22.23.2): java.lang.RuntimeException: org.apache.hadoop.hive.ql.pl.exception.PLException: Hive exception
SELECT test_set(ENAME,JOB) FROM EMP_TORC WHERE ENAME='JONES';

正常的 call 或者 begin end 方式调用 function,是在 server 端执行的,像“标准sql”和“set_env”是需要 server context 来执行的。
而 sql 里面调用 function 的话,是在 executor 端跑的,executor 端没有 server 的 context,无法从头开始编译优化执行 sql,所以会失败。
后面如果需要结合一些 set 命令来执行 sql 语句的 function 话,建议先在 session 里面 set,然后再 sql 调用 function。