首页 > 解决方案 > 对于 Snowflake .NET 连接器,我可以在原始(Pascal)外壳中获取列名吗?

问题描述

我正在尝试从雪花数据集自动构建 Excel 文档。我在 C# Core 3.1 中使用 .NET 连接器。但是列名都以大写形式返回,这使得它们难以解释,因为原始列名在数据库中使用 pascal 大小写。是否可以以保留列名的原始大小写的方式设置连接器或查询架构?(我没有重命名数据库中的列的选项)我尝试使用“GetSchemaTable”方法和“GetColumnSchema”方法,如下所示。

const string DATABASE_NAME = "MY_DB";
const string SCHEMA_NAME = "PUBLIC";
const string TABLE_NAME = "VW_FACT";

[Test]
public void GetColumnNamesFromTableUsingColumnSchema()
{
  // Arrange...
  var script = $"USE DATABASE {DATABASE_NAME}; SELECT * FROM {SCHEMA_NAME}.{TABLE_NAME}";
  DbDataReader actualDataset = GetDataSetFromSnowflake(script);
  // Act...
  IEnumerable<string> columnNames = GetTableNamesUsingColumnSchemaMethod(actualDataset);
  // Assert...
  Assert.AreEqual(expected: "CanTread", actual: columnNames.ElementAt(0)); 
  // actual = "CANTREAD"
}

[Test]
public void GetColumnNamesFromTableUsingTableSchema()
{
  // Arrange...
  var script = $"USE DATABASE {DATABASE_NAME}; SELECT * FROM {SCHEMA_NAME}.{TABLE_NAME}";
  DbDataReader actualDataset = GetDataSetFromSnowflake(script);
  // Act...
  IEnumerable<string> columnNames = GetTableNamesUsingTableSchemaMethod(actualDataset);
  // Assert...
  Assert.AreEqual(expected: "CanTread", actual: columnNames.ElementAt(0)); 
  // actual = "CANTREAD"
}

public DbDataReader GetDataSetFromSnowflake(string script) {
  var connection = new SnowflakeDbConnection();
  connection.ConnectionString = SNOWFLAKE_CONNECTION_STRING;
  connection.Open();
  var cmd = connection.CreateCommand();
  // Convert script into series of queries... (because .NET connector can't execute scripts yet)
  var queries = script.Split(";").ToList(); 
  // Execute any queries prior to final query...
  queries.Take(queries.Count - 1).ToList().ForEach(q => { 
    cmd.CommandText = q;
    cmd.ExecuteNonQuery();
  });
  // Execute final query and return dataset...
  cmd.CommandText = queries.Last();
  var reader = cmd.ExecuteReader();
  connection.Close();
  return reader;
}

IEnumerable<string> GetTableNamesUsingTableSchemaMethod(DbDataReader reader)
{
  // Use GetSchemaTable...
  var tableSchema = reader.GetSchemaTable();
  var columnIndexForNameColumn = 2;
  for (int rowIndex = 0; rowIndex < tableSchema.Rows.Count; rowIndex++)
  {
    // Get the column name...
    yield return tableSchema.Rows[rowIndex].ItemArray[columnIndexForNameColumn].ToString();
  }
}

IEnumerable<string> GetTableNamesUsingColumnSchemaMethod(DbDataReader reader)
{
  // Use GetColumnSchema...
  var columnCollection = reader.GetColumnSchema();
  foreach (var dbCol in columnCollection)
  {
    // Get the column name...
    yield return dbCol.ColumnName;
  }
}

标签: c#snowflake-cloud-data-platform

解决方案


是否可以以保留列名的原始大小写的方式设置连接器或查询架构?

除非您引用定义对象名称的文字,否则它们始终存储为大写对象并以相同的方式解析。引用文档中的一些相关部分:

不带引号的对象标识符:

不区分大小写

当标识符未加引号时,它以大写形式存储和解析

[...]强烈建议您在实施 Snowflake 的早期选择标识符解析方法 [...]

原始大小写不会保留在存储的元数据中,因此除了检查构成查询的原始文本外,没有办法检索它。

我没有重命名数据库中的列的选项

如果区分大小写的命名对您的业务逻辑很重要,您将必须使用带引号的文字重新创建表,这也将要求您始终以相同的形式引用它们:

CREATE TABLE "TableNameWithPreservedCasing" ("ColumnNameToo" string);

SELECT "ColumnNameToo" FROM "TableNameWithPreservedCasing";

推荐阅读