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

时间:2019-12-10 13:43:02

标签: snowflake-data-warehouse

背景

我正在使用Azure数据工厂v2将本地数据库(例如SQL Server)的数据加载到Azure数据湖gen2。由于要加载数千个表,因此我创建了一个动态ADF管道,该管道根据模式,表名,修改日期(用于标识增量)等参数按原样加载源中的数据。显然,这意味着我无法在ADF中手动指定任何类型的架构或映射。很好,因为我希望数据湖以相同的结构保存源数据的持久性副本。数据已加载到ORC文件中。

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

问题

由于列名称在Snowflake中始终为大写,并且在许多方面都区分大小写,因此Snowflake无法使用动态生成的DDL语句解析ORC文件,因为虚拟列的定义不再与源列对应名称框。例如,它将生成一个虚拟列为-> ID NUMBER AS(value:ID :: NUMBER)

这将返回NULL,因为该列在源数据库中(因此也在数据湖的ORC文件中)用小写D命名为“ Id”。

这似乎是Snowflake的主要缺点。有没有解决这个问题的合理方法?我唯一能想到的选择是: 1.将信息模式从源数据库分别加载到Snowflake,然后使用该数据构建带有正确的带大小写的列名的正确虚拟列定义。 2.将记录全部加载到Snowflake的某个变体列中,转换为UPPER或LOWER。

这两个选项都增加了很多复杂性,甚至使数据混乱。有什么简单的方法只从ORC文件返回列名吗?最终,我将需要能够在数据湖中的文件上使用诸如Snowflake的DESCRIBE TABLE之类的东西。

2 个答案:

答案 0 :(得分:0)

除非您设置参数QUOTED_IDENTIFIERS_IGNORE_CASE = TRUE,否则您可以在所需的大小写中声明您的列:

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

如果动态SQL小心地使用"Id"而不是Id,那么您会没事的。

答案 1 :(得分:0)

找到了一种更好的方法来实现这一目标,所以我在回答自己的问题。

通过以下查询,我们可以直接从阶段中的ORC文件获取路径/列名称,并带有来自源的数据类型提示。这样可以过滤出仅包含NULL值的列。很有可能会创建某种类型的数据类型排序表,以便最终确定我们要为外部表动态定义的虚拟列的最终数据类型。

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