如何 return table 在 Snowflake 的 SQL 存储过程中创建和删除的计数?
How to return the count of a table created and dropped within a SQL stored procedure in Snowflake?
我正在尝试使用变量将计数存储在 Snowflake 的存储过程中创建的临时 table 中,以便我可以将值包含在 return 语句中。当我尝试从 table 执行 select count(*) 时,我得到 SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
。如果我尝试使用 LET 创建一个变量,我会得到同样的错误。如果我使用 SET 创建会话变量,它不会立即出错,但之后我无法访问会话变量(我猜会话变量在存储过程中不起作用)。从 create table 语句中删除临时关键字没有帮助。
但是,我可以在更新语句(第 36-48 行)中使用 table,并且工作正常。有没有一种方法可以存储在存储过程中创建和删除的 table 的计数,以便在 return 语句中使用?我想我可以使用在子查询中创建 temp table 的逻辑并直接获取计数,但我真的不想这样做(此代码是创建 temp [= 的查询的简化版本22=] 并且它实际上对多个联合和连接非常笨重)。
CREATE OR REPLACE PROCEDURE DOMAIN_CANONICAL.MFG_ITEM_LOAD_test(X_DAYS_BACK INTEGER)
returns string not null
language SQL
as
$$
BEGIN
LET TIMESTAMP_NOW TIMESTAMP := CURRENT_TIMESTAMP() ;
CREATE OR REPLACE TEMPORARY TABLE DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM (
GHX_INTERNAL_ITEM_ID STRING,
TRADEMARK_BRANDNAME STRING,
DEVICE_PUBLISH_DATE STRING,
CDP__ETL_INSERT_TIMESTAMP TIMESTAMP,
CDP__ETL_UPDATE_TIMESTAMP TIMESTAMP,
HASH_DELTA STRING
)
AS
SELECT *, MD5(
HASH(TRADEMARK_BRANDNAME) ||
HASH(DEVICE_PUBLISH_DATE)) AS HASH_DELTA
FROM(
SELECT
'GUDID'||DEVICE.PRIMARY_DI AS GHX_INTERNAL_ITEM_ID,
DEVICE.BRAND_NAME AS TRADEMARK_BRANDNAME,
DEVICE.DEVICE_PUBLISH_DATE AS DEVICE_PUBLISH_DATE,
:TIMESTAMP_NOW AS CDP__ETL_INSERT_TIMESTAMP,
:TIMESTAMP_NOW AS CDP__ETL_UPDATE_TIMESTAMP
FROM BASE.GUDID_DEVICE DEVICE
WHERE
DEVICE.CDP__ETL_UPDATE_TIMESTAMP >= DATEADD(Day ,-1*:X_DAYS_BACK, CURRENT_DATE)
);
-- Successfully updates existing rows with changes using the temp table
UPDATE DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
SET
MI.TRADEMARK_BRANDNAME = DMI.TRADEMARK_BRANDNAME,
MI.DEVICE_PUBLISH_DATE = DMI.DEVICE_PUBLISH_DATE,
CDP__ETL_UPDATE_TIMESTAMP = :TIMESTAMP_NOW
FROM DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
WHERE MI.GHX_INTERNAL_ITEM_ID IN (
SELECT MI.GHX_INTERNAL_ITEM_ID FROM CDP_sms.DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
WHERE MI.HASH_DELTA != DMI.HASH_DELTA
)
AND MI.GHX_INTERNAL_ITEM_ID = DMI.GHX_INTERNAL_ITEM_ID;
// let UPDATED_ROW_COUNT INTEGER := (select count(*) FROM DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
// INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
// ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
// where MI.HASH_DELTA != DMI.HASH_DELTA);
//// -- If Lines 52-55 are uncommented: SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
// set UPDATED_ROW_COUNT = (select count(*) from DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI);
// return $UPDATED_ROW_COUNT;
//// If 58/59 are uncommented: -- SQL compilation error: error line 59 at position 10 Session variable '$UPDATED_ROW_COUNT' does not exist
//return (select count(*) from DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM);
//// If above line uncommented: -- SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
DROP TABLE IF EXISTS DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM;
let UPDATED_ROW_COUNT INTEGER := 100;
RETURN 'DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp updated with ' || :UPDATED_ROW_COUNT || ' rows';
END;
$$
使用INTO
:
LET UPDATED_ROW_COUNT INT;
select count(*)
INTO :UPDATED_ROW_COUNT
FROM DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
where MI.HASH_DELTA != DMI.HASH_DELTA;
您始终可以使用全局变量SQLROWCOUNT,例如:
CREATE OR REPLACE PROCEDURE SP_TEST()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
row_cnt INT := 0;
BEGIN
CREATE OR REPLACE LOCAL TEMP TABLE tempTB
AS
SELECT SEQ4()+1 AS val, 100 AS a
FROM TABLE(GENERATOR(ROWCOUNT => 1000)) AS t;
UPDATE tempTB
SET a = 200
WHERE val BETWEEN 301 AND 800;
row_cnt := IFNULL(SQLROWCOUNT, 0)::int;
DROP TABLE IF EXISTS tempTB;
RETURN 'Rows Affected: ' || row_cnt;
END;
$$;
CALL SP_TEST();
Result:
Rows Affected: 500
我正在尝试使用变量将计数存储在 Snowflake 的存储过程中创建的临时 table 中,以便我可以将值包含在 return 语句中。当我尝试从 table 执行 select count(*) 时,我得到 SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
。如果我尝试使用 LET 创建一个变量,我会得到同样的错误。如果我使用 SET 创建会话变量,它不会立即出错,但之后我无法访问会话变量(我猜会话变量在存储过程中不起作用)。从 create table 语句中删除临时关键字没有帮助。
但是,我可以在更新语句(第 36-48 行)中使用 table,并且工作正常。有没有一种方法可以存储在存储过程中创建和删除的 table 的计数,以便在 return 语句中使用?我想我可以使用在子查询中创建 temp table 的逻辑并直接获取计数,但我真的不想这样做(此代码是创建 temp [= 的查询的简化版本22=] 并且它实际上对多个联合和连接非常笨重)。
CREATE OR REPLACE PROCEDURE DOMAIN_CANONICAL.MFG_ITEM_LOAD_test(X_DAYS_BACK INTEGER)
returns string not null
language SQL
as
$$
BEGIN
LET TIMESTAMP_NOW TIMESTAMP := CURRENT_TIMESTAMP() ;
CREATE OR REPLACE TEMPORARY TABLE DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM (
GHX_INTERNAL_ITEM_ID STRING,
TRADEMARK_BRANDNAME STRING,
DEVICE_PUBLISH_DATE STRING,
CDP__ETL_INSERT_TIMESTAMP TIMESTAMP,
CDP__ETL_UPDATE_TIMESTAMP TIMESTAMP,
HASH_DELTA STRING
)
AS
SELECT *, MD5(
HASH(TRADEMARK_BRANDNAME) ||
HASH(DEVICE_PUBLISH_DATE)) AS HASH_DELTA
FROM(
SELECT
'GUDID'||DEVICE.PRIMARY_DI AS GHX_INTERNAL_ITEM_ID,
DEVICE.BRAND_NAME AS TRADEMARK_BRANDNAME,
DEVICE.DEVICE_PUBLISH_DATE AS DEVICE_PUBLISH_DATE,
:TIMESTAMP_NOW AS CDP__ETL_INSERT_TIMESTAMP,
:TIMESTAMP_NOW AS CDP__ETL_UPDATE_TIMESTAMP
FROM BASE.GUDID_DEVICE DEVICE
WHERE
DEVICE.CDP__ETL_UPDATE_TIMESTAMP >= DATEADD(Day ,-1*:X_DAYS_BACK, CURRENT_DATE)
);
-- Successfully updates existing rows with changes using the temp table
UPDATE DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
SET
MI.TRADEMARK_BRANDNAME = DMI.TRADEMARK_BRANDNAME,
MI.DEVICE_PUBLISH_DATE = DMI.DEVICE_PUBLISH_DATE,
CDP__ETL_UPDATE_TIMESTAMP = :TIMESTAMP_NOW
FROM DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
WHERE MI.GHX_INTERNAL_ITEM_ID IN (
SELECT MI.GHX_INTERNAL_ITEM_ID FROM CDP_sms.DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
WHERE MI.HASH_DELTA != DMI.HASH_DELTA
)
AND MI.GHX_INTERNAL_ITEM_ID = DMI.GHX_INTERNAL_ITEM_ID;
// let UPDATED_ROW_COUNT INTEGER := (select count(*) FROM DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
// INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
// ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
// where MI.HASH_DELTA != DMI.HASH_DELTA);
//// -- If Lines 52-55 are uncommented: SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
// set UPDATED_ROW_COUNT = (select count(*) from DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI);
// return $UPDATED_ROW_COUNT;
//// If 58/59 are uncommented: -- SQL compilation error: error line 59 at position 10 Session variable '$UPDATED_ROW_COUNT' does not exist
//return (select count(*) from DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM);
//// If above line uncommented: -- SQL compilation error: Object 'CDP_SMS.DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM' does not exist or not authorized.
DROP TABLE IF EXISTS DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM;
let UPDATED_ROW_COUNT INTEGER := 100;
RETURN 'DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp updated with ' || :UPDATED_ROW_COUNT || ' rows';
END;
$$
使用INTO
:
LET UPDATED_ROW_COUNT INT;
select count(*)
INTO :UPDATED_ROW_COUNT
FROM DOMAIN_CANONICAL.MANUFACTURER_ITEM_temp MI
INNER JOIN DOMAIN_CANONICAL.TEMP_DELTA_MANUFACTURER_ITEM DMI
ON DMI.GHX_INTERNAL_ITEM_ID = MI.GHX_INTERNAL_ITEM_ID
where MI.HASH_DELTA != DMI.HASH_DELTA;
您始终可以使用全局变量SQLROWCOUNT,例如:
CREATE OR REPLACE PROCEDURE SP_TEST()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
row_cnt INT := 0;
BEGIN
CREATE OR REPLACE LOCAL TEMP TABLE tempTB
AS
SELECT SEQ4()+1 AS val, 100 AS a
FROM TABLE(GENERATOR(ROWCOUNT => 1000)) AS t;
UPDATE tempTB
SET a = 200
WHERE val BETWEEN 301 AND 800;
row_cnt := IFNULL(SQLROWCOUNT, 0)::int;
DROP TABLE IF EXISTS tempTB;
RETURN 'Rows Affected: ' || row_cnt;
END;
$$;
CALL SP_TEST();
Result:
Rows Affected: 500