问题描述
我正在使用存储在 Azure Data Lake Storage 中的 CSV 创建外部表,并使用 sql Server 中的 polybase 填充该表。
但是,我遇到了这个问题,并认为这可能是由于在某一特定列中字符串中存在双引号,并且字符串分隔符已在 polybase {{ 中指定为 "
1}}。
(STRING_DELIMITER = '"')
示例:
我对此进行了相当广泛的研究,发现这个问题已经存在多年,但尚未找到任何解决方案。
任何帮助将不胜感激。
解决方法
我认为解决这个问题的最简单方法是使用一个不是逗号的分隔符,而不是字符串分隔符,因为您负责 .csv 创建。使用您知道不会出现在文件中的分隔符。我在我的例子中使用了一个管道,一旦它被导入到数据库中,我就会清理这个字符串。
一个简单的例子:
IF EXISTS ( SELECT * FROM sys.external_tables WHERE name = 'delimiterWorking' )
DROP EXTERNAL TABLE delimiterWorking
GO
IF EXISTS ( SELECT * FROM sys.tables WHERE name = 'cleanedData' )
DROP TABLE cleanedData
GO
IF EXISTS ( SELECT * FROM sys.external_file_formats WHERE name = 'ff_delimiterWorking' )
DROP EXTERNAL FILE FORMAT ff_delimiterWorking
GO
CREATE EXTERNAL FILE FORMAT ff_delimiterWorking
WITH (
FORMAT_TYPE = DELIMITEDTEXT,FORMAT_OPTIONS (
FIELD_TERMINATOR = '|',--STRING_DELIMITER = '"',FIRST_ROW = 2,ENCODING = 'UTF8'
)
);
GO
CREATE EXTERNAL TABLE delimiterWorking (
id INT NOT NULL,body VARCHAR(8000) NULL
)
WITH (
LOCATION = 'yourLake/someFolder/delimiterTest6.txt',DATA_SOURCE = ds_azureDataLakeStore,FILE_FORMAT = ff_delimiterWorking,REJECT_TYPE = VALUE,REJECT_VALUE = 0
);
GO
SELECT *
FROM delimiterWorking
GO
-- Fix up the data
CREATE TABLE cleanedData
WITH (
CLUSTERED COLUMNSTORE INDEX,DISTRIBUTION = ROUND_ROBIN
)
AS
SELECT
id,body AS originalCol,SUBSTRING ( body,2,LEN(body) - 2 ) cleanBody
FROM delimiterWorking
GO
SELECT *
FROM cleanedData
我的结果:
,如果您将数据湖平面文件转换为 Parquet 格式,则可以避免字符串分隔符问题。
输入:
“ID” | “姓名” | “评论” |
---|---|---|
“1” | “戴夫” | “嗨,我是戴夫”来自“ |
“2” | “AARO” | “AARO” |
步骤:
1 将平面文件转换为 Parquet 格式[使用 Azure 数据工厂]
2 在数据湖中创建外部文件格式[假设主密钥,范围凭据可用]
CREATE EXTERNAL FILE FORMAT PARQUET_CONV
WITH (FORMAT_TYPE = PARQUET,DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);
3 使用 FILE_FORMAT = PARQUET_CONV 创建外部表
输出:
我相信这是最好的选择,因为微软目前没有解决方案来处理外部表数据中出现的这个字符串分隔符