Snowflake - 如何在过程中调用 UDF

Snowflake - How to call a UDF within a Procedure

在下面,TEST_DATA 是我的数据,TEST_VALIDATE 是我要验证的 table。我想针对 TEST_VALIDATE 测试 TEST_DATA.DVALUE 并调整 DVALUE 以使其始终在给定范围内。 UDF TEST_RANGE() 执行此操作并且 returns 调整后的缓冲值:

CREATE TABLE TEST_DATA
(
  MNEMONIC      VARCHAR2(3),
  DVALUE        NUMBER(5,1)
);

INSERT INTO TEST_DATA ( MNEMONIC, DVALUE ) VALUES ( 'AT', 2 );
INSERT INTO TEST_DATA ( MNEMONIC, DVALUE ) VALUES ( 'BP', 88 );

CREATE TABLE TEST_VALIDATE
(
  MNEMONIC          VARCHAR2(3),
  MINIMUM_VALUE     NUMBER(5,1),
  MAXIMUM_VALUE     NUMBER(5,1)
);

INSERT INTO TEST_VALIDATE ( MNEMONIC, MINIMUM_VALUE, MAXIMUM_VALUE ) VALUES ( 'AT', 5.1, 10.1 );
INSERT INTO TEST_VALIDATE ( MNEMONIC, MINIMUM_VALUE, MAXIMUM_VALUE ) VALUES ( 'BP', 2.2, 100.2 );


CREATE OR REPLACE FUNCTION TEST_RANGE( p_mnemonic VARCHAR2, p_reading NUMBER(5,1) )
RETURNS NUMBER AS
'SELECT
MAX(CASE
    WHEN p_reading BETWEEN MINIMUM_VALUE AND MAXIMUM_VALUE THEN p_reading
    WHEN p_reading < MINIMUM_VALUE THEN MINIMUM_VALUE
    WHEN p_reading > MAXIMUM_VALUE THEN MAXIMUM_VALUE
    ELSE NULL
END)
FROM TEST_VALIDATE
WHERE MNEMONIC = p_mnemonic';

这个测试执行得很好:

SELECT TEST_RANGE( 'AT', 55 );

但这会引发以下错误“002031 (42601): SQL 编译错误: 无法评估不支持的子查询类型”——为什么:

SELECT TEST_RANGE( MNEMONIC, DVALUE ) FROM TEST_DATA;

所以我想创建一个存储过程来做这个,但是你如何在一个过程中调用一个UDF?我认为这是非常基本的,但我在上面找不到任何 post。我是否必须将 UDF 包装在 createStatement().execute().getColumnValue() 例程中?还有比这更易读的方式吗?

CREATE OR REPLACE PROCEDURE EDW_WEATHER.TEST_SP ()
 RETURNS VARIANT
 LANGUAGE JAVASCRIPT
AS $$
  var rs = snowflake.createStatement( { sqlText: `SELECT MNEMONIC, DVALUE FROM TEST_DATA`, binds:[] } ).execute();

  var results_array = [];
  while (rs.next()) {
    // This is wrong. How do I call the UDF???
    results_array.push( rs.select( TEST_RANGE( rs.getColumnValue('MNEMONIC'), rs.getColumnValue('DVALUE') ) ) );
  }
  return results_array;
$$

要回答您的最后一个问题,您如何在存储过程中调用 UDF:您可以像在 SP 外部一样触发 UDF。

您必须使用 .execute() 方法,用它触发 SELECT myUDF(),然后检索结果集以供进一步使用和处理。

您的 SP 可能如下所示:

CREATE OR REPLACE PROCEDURE TEST_SP ()
 RETURNS VARIANT
 LANGUAGE JAVASCRIPT
AS $$
  var rs = snowflake.createStatement( { sqlText: `SELECT MNEMONIC, DVALUE FROM TEST_DATA`, binds:[] } ).execute();

  var results_array = [];
  while (rs.next()) {
    var sub_rs = snowflake.createStatement( { 
        sqlText: `SELECT TEST_RANGE(?, ?)`, 
        binds:[
            rs.getColumnValue('MNEMONIC'), 
            rs.getColumnValue('DVALUE')
        ] } 
    ).execute();
    
    sub_rs.next();
    results_array.push(sub_rs.getColumnValue(1));
  }
  return results_array;
$$;

基本上它与您 运行 SELECT 语句的方式相同。