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
我很难部署它,我需要将雪花数据卸载到数据框中。我们要读取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 |