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 语句的方式相同。
在下面,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 语句的方式相同。