String delimiter present in string not permitted in Polybase?

Viewed 659

I'm creating an external table using a CSV stored in an Azure Data Lake Storage and populating the table using Polybase in SQL Server.

However, I ran into this problem and figured it may be due to the fact that in one particular column there are double quotes present within the string, and the string delimiter has been specified as " in Polybase (STRING_DELIMITER = '"').

HdfsBridge::recordReaderFillBuffer - Unexpected error encountered filling record reader buffer: HadoopExecutionException: Could not find a delimiter after string delimiter

Example:

enter image description here

I have done quite an extensive research in this and found that this issue has been around for years but yet to see any solutions given.

Any help will be appreciated.

2 Answers

I think the easiest way to fix this up because you are in charge of the .csv creation is to use a delimiter which is not a comma and leave off the string delimiter. Use a separator which you know will not appear in the file. I've used a pipe in my example, and I clean up the string once it is imported in to the database.

A simple example:

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

My results:

My results

String Delimiter issue can be avoided if you have the Data lake flat file converted to Parquet format.

Input:

"ID" "NAME" "COMMENTS"
"1" "DAVE" "Hi "I am Dave" from"
"2" "AARO" "AARO"

Steps:

1 Convert Flat file to Parquet format [Using Azure Data factory]

2 Create External File format in Data Lake [Assuming Master key, Scope credentials available]

CREATE EXTERNAL FILE FORMAT PARQUET_CONV
WITH (FORMAT_TYPE = PARQUET, 
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);

3 Create External Table with FILE_FORMAT = PARQUET_CONV

Output:

enter image description here

I believe this is the best option as Microsoft don't have an solution currently to handle this string delimiter occurring with in the data for External table

Related