如何 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; 

相关:Setting Variables to the Results of a SELECT Statement

您始终可以使用全局变量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