Synapse专用SQL池外部表插入报错:bigint转date不允许
问题分析与解决
你遇到的问题核心是Parquet文件中日期列的实际存储类型是BIGINT(比如Epoch天数/毫秒数),但你在外部表定义里指定了DATE类型,Synapse专用SQL池无法自动完成这种显式转换,所以查询或插入时触发错误。
解决步骤
1. 确认Parquet中日期列的存储格式
先搞清楚Parquet里Column1/Column2/Column3是用什么格式存储的:
- 是从1970-01-01开始的天数(比如19000代表2022-02-20)
- 还是从1970-01-01开始的毫秒数(比如1645324800000代表2022-02-20)
可以用Synapse的OPENROWSET直接读取文件查看原始值:
SELECT TOP 10 Column1, Column2, Column3 FROM OPENROWSET( BULK '/Path/To/Parquet/', DATA_SOURCE = 'gold_dbx', FORMAT = 'PARQUET' ) AS [result]
2. 修改外部表定义并手动转换类型
先把外部表中DATE类型的列临时改为BIGINT,然后在查询/插入时手动转换为DATE:
修改后的外部表定义
CREATE EXTERNAL TABLE [gold].[ExternalTable] ( [Column1] [BIGINT] NULL -- 改成BIGINT匹配Parquet实际类型 ,[Column2] [BIGINT] NULL ,[Column3] [BIGINT] NULL ,[Column4] [DATETIME2] NULL ,[Column5] [DATETIME2] NULL ,[Column6] [SMALLINT] NULL ,[Column7] [BIGINT] NULL ,[Column8] [BIGINT] NULL ,[Column9] [BIGINT] NULL ,[Column10] [VARBINARY] (8000) NULL ,[Column11] [VARCHAR] (8000) NULL ,[Column12] [VARCHAR] (8000) NULL ,[Column13] [VARCHAR] (8000) NULL ,[Column14] [VARCHAR] (8000) NULL ,[Column15] [VARCHAR] (8000) NULL ,[Column16] [VARCHAR] (8000) NULL ,[Column17] [VARCHAR] (8000) NULL ,[Column18] [VARCHAR] (8000) NULL ,[Column19] [VARCHAR] (8000) NULL ,[Column20] [VARCHAR] (8000) NULL ,[Column21] [VARCHAR] (8000) NULL ,[Column22] [VARCHAR] (8000) NULL ,[Column23] [VARCHAR] (8000) NULL ,[Column24] [VARCHAR] (8000) NULL ,[Column25] [VARCHAR] (8000) NULL ,[Column26] [VARCHAR] (8000) NULL ,[Column27] [VARCHAR] (8000) NULL ,[Column28] [VARCHAR] (8000) NULL ,[Column29] [VARCHAR] (8000) NULL ) WITH (DATA_SOURCE = [gold_dbx], LOCATION = N'/Path/To/Parquet/', FILE_FORMAT = [ParquetFormat], REJECT_TYPE = VALUE, REJECT_VALUE = 0 );
插入时根据存储格式转换类型
- 如果是Epoch天数:
INSERT INTO [gold].[Table] SELECT DATEADD(DAY, Column1, '1970-01-01') AS Column1, DATEADD(DAY, Column2, '1970-01-01') AS Column2, DATEADD(DAY, Column3, '1970-01-01') AS Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10, Column11, Column12, Column13, Column14, Column15, Column16, Column17, Column18, Column19, Column20, Column21, Column22, Column23, Column24, Column25, Column26, Column27, Column28, Column29 FROM [gold].[ExternalTable]
- 如果是Epoch毫秒数:
INSERT INTO [gold].[Table] SELECT CAST(DATEADD(MILLISECOND, Column1, '1970-01-01') AS DATE) AS Column1, CAST(DATEADD(MILLISECOND, Column2, '1970-01-01') AS DATE) AS Column2, CAST(DATEADD(MILLISECOND, Column3, '1970-01-01') AS DATE) AS Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10, Column11, Column12, Column13, Column14, Column15, Column16, Column17, Column18, Column19, Column20, Column21, Column22, Column23, Column24, Column25, Column26, Column27, Column28, Column29 FROM [gold].[ExternalTable]
3. 额外注意点
- 如果你能修改Parquet文件的生成逻辑,建议直接将日期列存储为标准DATE类型,这样后续就不需要手动转换。
- 检查你的Parquet文件格式定义
[ParquetFormat],确保没有错误的类型映射配置,默认的Parquet格式定义已经能正确识别标准日期类型。
内容的提问来源于stack exchange,提问作者Rchee
相关产品推荐
相关产品推荐

