Databricks DLT提取JSON字段报StructField引用歧义错误
报错根因
这个字段歧义报错是两个问题叠加导致的:
- Bronze层建表时使用
SELECT *搭配Auto Loader的addNewColumnsschema演化模式,存储在/mnt/dlt/schema/fixture路径下的历史推断schema残留了重复的id字段元数据——通常是早期读取格式异常的JSON文件、或schema演化过程中字段重复注册导致的,你提供的JSON样例本身结构不存在重复id问题。 - Silver层CTE写法缺失
AS关键字,且使用链式点号访问多层嵌套字段时,Spark SQL解析器碰到携带重复字段元数据的结构体,无法精准定位目标id字段,直接抛出歧义错误。
修复步骤
- 清理历史schema缓存:删除
/mnt/dlt/schema/fixture路径下的所有历史schema文件,否则DLT会持续沿用旧的错误schema,代码修改不会生效。 - 调整Bronze层建表逻辑:禁止使用
SELECT *读取所有自动推断的字段,显式声明需要保留的顶层字段,从源头避免异常字段、重复字段进入表结构。 - 修正Silver层查询逻辑:补全CTE语法缺失的
AS关键字,保持嵌套字段引用路径清晰。
修正后的完整DLT代码
-- Bronze层:显式指定读取字段,避免SELECT *带入异常字段 CREATE OR REFRESH STREAMING LIVE TABLE fixture_raw AS SELECT get, parameters, response, input_file_name() AS InputFile, now() AS LoadTime FROM cloud_files( "/mnt/input/fixtures/", "json", map( "cloudFiles.inferColumnTypes", "true", "cloudFiles.schemaLocation", "/mnt/dlt/schema/fixture", "cloudFiles.schemaEvolutionMode", "addNewColumns" ) ); -- Silver层:补全CTE的AS关键字,明确嵌套字段引用路径 CREATE OR REFRESH LIVE TABLE fixture_prepared AS WITH FixtureData AS ( SELECT explode(response) AS FixtureJson FROM live.fixture_raw ) SELECT FixtureJson.fixture.id AS FixtureID, FixtureJson.fixture.date AS StartTime, FixtureJson.fixture.venue.name AS Venue, FixtureJson.teams.home.id AS HomeTeamID, FixtureJson.teams.home.name AS HomeTeamName, FixtureJson.teams.away.id AS AwayTeamID, FixtureJson.teams.away.name AS AwayTeamName FROM FixtureData;
可选增强(彻底规避字段歧义)
如果清理schema、修正代码后仍偶发歧义报错,可以在访问嵌套字段时使用getField方法显式指定字段名,绕开Spark解析器的模糊匹配逻辑,示例写法:
SELECT FixtureJson.fixture.getField("id") AS FixtureID, FixtureJson.fixture.getField("date") AS StartTime, FixtureJson.fixture.venue.getField("name") AS Venue, FixtureJson.teams.home.getField("id") AS HomeTeamID, FixtureJson.teams.home.getField("name") AS HomeTeamName, FixtureJson.teams.away.getField("id") AS AwayTeamID, FixtureJson.teams.away.getField("name") AS AwayTeamName FROM FixtureData;
注意:修改完代码后需要对两张表执行全量刷新(Full Refresh),才能让新的表结构生效。
内容的提问来源于stack exchange,提问作者Magnus Johannesson
相关产品推荐
相关产品推荐

