Snowflake cloud data platform 如何处理大数据文件格式和外部表中区分大小写的列名?

Snowflake cloud data platform 如何处理大数据文件格式和外部表中区分大小写的列名?,snowflake-cloud-data-platform,Snowflake Cloud Data Platform,背景 我正在使用Azure data factory v2将数据从on prem数据库(例如SQL Server)加载到Azure data lake gen2。因为我要加载数千个表,所以我创建了一个动态ADF管道,它根据模式、表名、修改日期(用于标识增量)等参数按源中的状态加载数据。这显然意味着我不能在ADF中手动指定任何类型的模式或映射。这很好,因为我希望数据湖在相同的结构中保存源数据的持久副本。数据被加载到ORC文件中 基于这些ORC文件,我想在Snowflake中创建带有虚拟列的外部表。

背景

我正在使用Azure data factory v2将数据从on prem数据库(例如SQL Server)加载到Azure data lake gen2。因为我要加载数千个表,所以我创建了一个动态ADF管道,它根据模式、表名、修改日期(用于标识增量)等参数按源中的状态加载数据。这显然意味着我不能在ADF中手动指定任何类型的模式或映射。这很好,因为我希望数据湖在相同的结构中保存源数据的持久副本。数据被加载到ORC文件中

基于这些ORC文件,我想在Snowflake中创建带有虚拟列的外部表。我已经在Snowflake中创建了普通表,它们的列名和数据类型与源表中的相同,我将在以后的阶段中使用它们。我想使用这些表的信息模式为外部表动态创建DDL语句

SELECT f.path as "ColumnName" 
          , TYPEOF(f.value) as "DataType"
          , COUNT(1) as NbrOfRecords
FROM (
        SELECT $1 as "value" FROM @<db>.<schema>.<stg>/<directory>/ (FILE_FORMAT => '<fileformat>')
    ), 
        lateral flatten(value, recursive=>true) f
        WHERE TYPEOF(f.value) != 'NULL_VALUE'
        GROUP BY f.path, TYPEOF(f.value)
        ORDER BY 1
问题

因为在Snowflake中列名总是大写的,并且在许多方面它是区分大小写的,所以Snowflake无法用动态生成的DDL语句解析ORC文件,因为虚拟列的定义不再与源列名大小写对应。例如,它将生成一个虚拟列as->ID NUMBER as(值:ID::NUMBER)

这将返回NULL,因为在源数据库中,列名为“Id”,小写为D,因此在数据湖的ORC文件中也是如此

这感觉像雪花的一个主要缺点。有什么合理的方法来解决这个问题吗?我能想到的唯一选择是: 1.将信息架构从源数据库分别加载到Snowflake,并使用该数据构建具有正确大小写列名的正确虚拟列定义。 2.将记录全部加载到Snowflake中的某个变量列中,转换为UPPER或LOWER


这两个选项都增加了很多复杂性,甚至弄乱了数据。有没有直接的方法只从ORC文件返回列名?最终,我需要能够在数据湖中的文件上使用类似Snowflake的描述表。

除非设置参数
QUOTED\u IDENTIFIERS\u IGNORE\u CASE=TRUE
,否则可以在所需的大小写中声明列:

CREATE TABLE "MyTable" ("Id" NUMBER);

如果您的动态SQL小心地使用
“Id”
,而不仅仅是
Id
,您就会没事。

找到了更好的方法来实现这一点,所以我要回答自己的问题

通过下面的查询,我们可以直接从stage中的ORC文件中获取路径/列名,并从源代码中获得数据类型的提示。这将过滤掉只包含空值的列。将很可能创建某种类型的数据类型排名表,用于最终确定虚拟列的数据类型,我们的目标是为外部表动态定义虚拟列

SELECT f.path as "ColumnName" 
          , TYPEOF(f.value) as "DataType"
          , COUNT(1) as NbrOfRecords
FROM (
        SELECT $1 as "value" FROM @<db>.<schema>.<stg>/<directory>/ (FILE_FORMAT => '<fileformat>')
    ), 
        lateral flatten(value, recursive=>true) f
        WHERE TYPEOF(f.value) != 'NULL_VALUE'
        GROUP BY f.path, TYPEOF(f.value)
        ORDER BY 1
选择f.path作为“ColumnName”
,TYPEOF(f.value)为“数据类型”
,将(1)计为记录
从(
从@..//(文件格式=>'')中选择$1作为“值”
), 
横向展平(值,递归=>真)f
其中TYPEOF(f.value)!='空值'
按f.path、TYPEOF(f.value)分组
按1订购

您能否更改生成DDL的脚本以在列名周围加引号?需要注意的是,如果您创建的列大小写混合,您将始终必须在Snowflake中引用列名。在这种情况下,我是否引用列名并不重要。该列在ORC文件中命名为dataValue,大写V。使用location=@stg file\u format=(format\u NAME='formatname'type=ORC)创建或替换外部表ext\u tablename(datavalue timestamp as(value:“datavalue”::timestamp)),这是否为空值?使用location=@stg file\u format=(format\u NAME='formatname'type=ORC)创建或替换外部表ext\u tablename(“dataValue”timestamp as(value:dataValue::timestamp)),因为它是虚拟列中value:definition的正确大小写,但关键是我想根据表的信息模式信息动态生成它,而不是像20世纪80年代那样手动编写所有虚拟列定义:)谢谢,因此,如果在创建表时将列名用引号括起来,则列名可以使用小写/混合大小写雪花信息模式存储—然后我可以使用与文件匹配的正确大小写,使用虚拟列定义解析文件Yes。信息架构视图
将提供与定义表列时在引号中使用的大小写完全相同的大小写