Snowflake 通过存储过程动态创建视图

Snowflake create views dynamically via stored procedure

我很难部署它,我需要将雪花数据卸载到数据框中。我们要读取snowflake的进程不能执行一个过程,只能调用一个table或者执行一个简单的查询。 snowflake 和一些 parquet 文件的数据类型不同,本质上是相同的数据,但另一个系统写的不同。

我的解决方案是立即读取信息模式以获取一种模式,table。然后我需要创建一个字符串来转换数据以与其他镶木地板文件兼容。

我在T-SQL、postgresql、plsql、nzsql中都写过类似的程序。当我尝试部署 DDL 时逻辑应该非常可靠我在循环中遇到错误,我做错了什么,雪花可以在 table 上循环我认为 FOR i IN (SELECT * FROM SYS_INFO_OUT) 语句是问题所在。

我已尝试更改循环结构的语法但无济于事,任何见解将不胜感激。

CREATE OR REPLACE PROCEDURE SCHEMA.VIEW_BUILDER()
returns varchar()
language sql
AS 
$$
DECLARE 
    qry_head varchar;
    qry_stmt varchar;
BEGIN
    DROP TABLE SYS_INFO_OUT;
    CREATE TEMP TABLE SYS_INFO_OUT AS
        SELECT tbl.TABLE_NAME,
            col.COLUMN_NAME,
            col.DATA_TYPE,
            COALESCE(col.CHARACTER_MAXIMUM_LENGTH,col.CHARACTER_OCTET_LENGTH,col.NUMERIC_PRECISION ,col.DATETIME_PRECISION) AS COL_LENGTH,
            col.ORDINAL_POSITION,
            col.IS_NULLABLE,
            CASE WHEN nvl(col.NUMERIC_SCALE,0) = 0 THEN 0 ELSE 1 END AS is_decimal
        FROM INFORMATION_SCHEMA.TABLES AS tbl
        INNER JOIN INFORMATION_SCHEMA.COLUMNS AS col ON tbl.TABLE_NAME = col.TABLE_NAME AND tbl.TABLE_SCHEMA = col.TABLE_SCHEMA
        WHERE tbl.TABLE_SCHEMA ='SOME_SCHMEA' AND tbl.TABLE_NAME ='SOME_TABLE'
        ORDER BY tbl.TABLE_NAME,
            col.ORDINAL_POSITION ASC;           
    FOR i IN (SELECT * FROM SYS_INFO_OUT )
    --Case statement to handle types
        SELECT 
            CASE DATA_TYPE
                WHEN 'NUMBER' THEN 
                    (
                    SELECT CASE 
                                WHEN is_decimal =1  THEN sql_stmt := sql_stmt + '(CAST '+ COLUMN_NAME +' as NUMBER(38,18)) as ' + COLUMN_NAME +','
                                ELSE sql_stmt := sql_stmt + '(CAST '+ COLUMN_NAME +' as varchar ) as ' + COLUMN_NAME +','
                            END )
                WHEN  'TEXT' THEN sql_stmt := sql_stmt + '(CAST '+ COLUMN_NAME +' as varchar ) as ' + COLUMN_NAME +','
                ELSE sql_stmt := sql_stmt + '(CAST '+ COLUMN_NAME +' as varchar ) as ' + COLUMN_NAME +','
            END
            sql_stmt = sql_stmt + ' '+ COLUMN_NAME
            sql_stmt = left(sql_stmt,(LENGTH(sql_stmt)-1))
    END LOOP;
        sql_stmt := sql_stmt +' FROM SOME_SCHMEA.SOME_TABLE'
        qry_head :=  'CREATE OR REPLACE VIEW ANOTHER_SCHEMA.VDF_SOME_TABLE AS SELECT ';
    EXECUTE IMMEDIATE (qry_head+sql_stmt);
    RETURN 'done';
END;
$

稍微清理了程序代码。 替换 CURSOR FOR LOOP

中需要的逻辑
CREATE OR REPLACE PROCEDURE VIEW_BUILDER()
returns varchar
language sql
AS 
$$
DECLARE 
    qry_head varchar := '';
    qry_stmt varchar := '';
    sql_stmt varchar := '';
BEGIN
    DROP TABLE IF EXISTS SYS_INFO_OUT;
    CREATE or replace TEMPORARY TABLE SYS_INFO_OUT AS
        SELECT tbl.TABLE_NAME,
            col.COLUMN_NAME,
            col.DATA_TYPE,
            COALESCE(col.CHARACTER_MAXIMUM_LENGTH,col.CHARACTER_OCTET_LENGTH,col.NUMERIC_PRECISION ,col.DATETIME_PRECISION) AS COL_LENGTH,
            col.ORDINAL_POSITION,
            col.IS_NULLABLE,
            CASE WHEN nvl(col.NUMERIC_SCALE,0) = 0 THEN 0 ELSE 1 END AS is_decimal
        FROM INFORMATION_SCHEMA.TABLES AS tbl
        INNER JOIN INFORMATION_SCHEMA.COLUMNS AS col ON tbl.TABLE_NAME = col.TABLE_NAME AND tbl.TABLE_SCHEMA = col.TABLE_SCHEMA
        WHERE tbl.TABLE_SCHEMA ='SOME_SCHMEA' AND tbl.TABLE_NAME ='SOME_TABLE'
        ORDER BY tbl.TABLE_NAME,
         col.ORDINAL_POSITION ASC;           
        let c1 cursor for SELECT * FROM SYS_INFO_OUT ;
        for record in c1 do
            qry_head:='x'; --- replace with code as needed
        end for;
    sql_stmt := sql_stmt ||'* FROM PUBLIC.TABLEA';
    qry_head :=  'CREATE OR REPLACE VIEW PUBLIC.VDF_SOME_TABLE AS SELECT ';
    EXECUTE IMMEDIATE (qry_head||sql_stmt);
    RETURN 'done';
END;
$$
;

call VIEW_BUILDER();
VIEW_BUILDER
done

检查是否正在创建过程中正在创建的视图 -

select count(*) from PUBLIC.VDF_SOME_TABLE;
COUNT(*)
1