【问题标题】:Synapse spark select column with space带空格的突触火花选择列
【发布时间】:2021-12-02 00:42:51
【问题描述】:

我正在尝试读取突触表,其中列名中有空格。

读取表一直在工作,直到我选择没有空格或特殊字符的列:

%%spark
val df = spark.read.synapsesql("<Pool>.<schema>.<table>").select("TYPE", "Year").limit(100)
df.show()

输出:

+------+----+
|  TYPE|Year|
+------+----+
|BOUGHT|LAST|
|BOUGHT|LAST|
|BOUGHT|LAST|
|BOUGHT|LAST|

当我开始选择带有空格的列时,我遇到了错误。我尝试了很多变种:

.select(col("""`Country Code`"""))
.select(col("`Country Code`"))
.select(col("""[Country Code]"""))
.select(col("Country Code"))
.select($"`Country Code`")
.select("`Country Code`")
.select("""`Country Code`""")

将返回此错误: 错误:com.microsoft.sqlserver.jdbc.SQLServerException:列名“国家/地区”无效。

如果我在选择中省略 `,例如:

.select("[Country Code]")

错误:com.microsoft.sqlserver.jdbc.SQLServerException:列名“[国家代码]”无效。

在突触中使用反引号火花只需将第一个单词作为列。

有什么经验吗?

【问题讨论】:

  • 你试过 df.printSchema() [没有 select 子句] 来查看 Spark 显示的列名吗?
  • 是的,我已经在检查空间是否真的是空间(并且空间是常规字符(32))。我在 MSSQL 工作室有连接,所以我可以看到所有表的详细信息。这个专栏就在那里。您有机会在您的 sybase 环境中尝试一下吗?
  • 我通过在原始选择中使用 `` 使其工作:.select("Id", "Country Code")
  • 这个我也试过了 :-/.
  • 不怀疑你,但评论没有正确呈现 - 国家代码周围的双引号内应该有反引号。

标签: scala apache-spark azure-synapse


【解决方案1】:

select 本身可以工作,添加show(或任何其他操作,如count)不会。 Synapse synapsesql API 似乎确实存在问题。 Invalid column name 'country' 错误来自 SQL 引擎,因为似乎无法将方括号传回给它。此外,parquet 文件不支持列名中的空格,因此它可能已连接。

解决方法是在列名中使用空格。如果需要,在之前的 Synapse 管道步骤中修复表。我会看看它,但可能没有其他答案。

如果要重命名数据库中的现有列,可以使用sp_rename,例如

EXEC sp_rename 'dbo.countries.country Type', 'countryType', 'COLUMN';

此代码已在 Synapse 专用 SQL 池上进行了测试。

不幸的是,那个特定的 API (sysnapsesql.read) 无法处理视图。您必须将其具体化,例如在之前的 Synapse Pipeline 步骤中使用 CTAS。 API 对简单模式有用(获取表格 -> 处理 -> 放回),但非常有限。您甚至无法管理表分布(散列、round_robin、复制)或索引(聚集列存储、聚集索引、堆)或分区,但您永远不知道它们有一天会添加到其中。无论如何,我会在下一次 MS 会议期间密切关注。

【讨论】:

  • 这方面有什么更新吗?我已经添加了我的 cmets 作为答案。如果您发现它们有用,请考虑点赞或标记为答案。
  • 是的,我有更新。问题是重命名列不是解决方案。我知道它可以解决问题,但就我而言,我无法重命名列。原因很简单,表和列用于其他进程,以及过程、视图等。如果我重命名该列,我将破坏整个数据库。但感谢您的帮助。
【解决方案2】:

我创建了使用JDBC 运行查询的函数。谢谢,我能够从视图中阅读。我添加了如何使用TokenLibrary 从 KeyVault 获取密码的 saplme 代码。

def spark_query(db, query):
    jdbc_hostname = "<synapse_db>.sql.azuresynapse.net"
    user = "<spark_db_client>"
    password = "<strong_password>"
    # password_from_kv = TokenLibrary.getSecret("<Linked_Key_Vault_Service_Name>", "<Key_Vault_Key_Name>", "<Key_Vault_Name>")
    return spark.read.format("jdbc") \
    .option("url", f"jdbc:sqlserver://{jdbc_hostname }:1433;databaseName={db};user={user};password={password}") \
    .option("query", query) \
    .load()

然后我创建了VIEW,列名不带空格:

CREATE VIEW v_my_table
AS
SELECT [Country code] as country_code from my_table

授予&lt;spark_db_client&gt;的访问权限:

GRANT SELECT ON v_my_table to <spark_db_client>

在整个准备之后,我能够从 VIEW 中读取表格并保存到 spark 数据库:

query = """
SELECT country_code FROM dbo.v_my_table
"""

df = spark_query(db="<my_database>", query=query)
spark.sql("CREATE DATABASE IF NOT EXISTS spark_poc")
df.write.mode("overwrite").saveAsTable("spark_poc.my_table")
df.registerTempTable("my_table")

这是&lt;placeholder_variables&gt;

【讨论】:

    猜你喜欢
    • 2019-03-30
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2020-09-09
    • 2019-03-03
    • 2013-10-25
    • 2013-02-04
    • 2015-10-04
    相关资源
    最近更新 更多