You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spark JDBC读取Azure SQL的LoadDate字段全为1900-01-01问题

问题描述

通过JDBC将Azure SQL数据库中的表读取到Databricks时,datetime类型的LoadDate字段返回值全为1900-01-01T00:00:00.000+0000。尝试在TSQL中创建视图转换该字段(比如用Year(f.LoadDate)提取年份),返回值却为0。其他同类型datetime字段可正常获取值,且LoadDate字段设置了MASKED WITH (FUNCTION = 'default()')。

相关代码

Databricks 读取代码

dbcHostName = "myserver.database.windows.net"
jdbcPort = "1433"
jdbcDatabase = "mydb"
connectionProperties = {
  "user":"myuser",
  "password":"mypwd",
  "driver" : "com.microsoft.sqlserver.jdbc.SQLServerDriver"
}
jdbcUrl = "jdbc:sqlserver://{0}:{1};database={2}".format(jdbcHostName,jdbcPort,jdbcDatabase)

pushdown_query = """(
    select top 100 * from dbo.vwExportTable
) t"""
df = spark.read.jdbc(url=jdbcUrl, table=pushdown_query, properties=connectionProperties)
display(df)

TSQL 视图定义

alter view vwExportTable
as
    select f.LoadDate, f.*,
    Year(f.LoadDate) y
    from edw.Fact f
where f.LoadDate > '2015-01-01'
;

表结构

CREATE TABLE [edw].[Fact](
    [BookingId] [int] NOT NULL,
    ...
    [BookingStartDate] [datetime] NOT NULL,
    ...
    [LoadDate] [datetime] MASKED WITH (FUNCTION = 'default()') NOT NULL,

) ON [PRIMARY]

原因分析

  1. 掩码函数生效机制:default()掩码函数针对datetime类型会返回该类型的默认值1900-01-01 00:00:00,这就是所有LoadDate返回值一致的原因。
  2. 过滤条件失效:视图中的where f.LoadDate > '2015-01-01'是基于掩码后的值判断的,而掩码后的值都是1900-01-01,根本不满足过滤条件。但因为使用了top 100,数据库仍然返回了掩码后的默认值,Year()作用在该值上自然得到0。
  3. 其他字段正常的原因:其他datetime字段没有配置掩码,所以能返回真实数据。

解决方案

  • 获取真实值:如果需要读取LoadDate的真实数据,需给当前数据库用户授予UNMASK权限,执行以下SQL:
    GRANT UNMASK TO myuser;
    
  • 调整掩码规则:如果不能授予UNMASK权限,可根据脱敏需求更换掩码函数,比如使用partial()保留部分日期信息:
    ALTER TABLE [edw].[Fact] ALTER COLUMN [LoadDate] MASKED WITH (FUNCTION = 'partial(1, "-", 10)');
    
  • 修正过滤逻辑:如果不需要真实值但要正确过滤,需确保过滤逻辑作用在真实数据上,比如使用拥有UNMASK权限的账号执行查询,或者在数据脱敏前完成过滤(如在数据库端用有权限的用户创建预处理视图)。

内容的提问来源于stack exchange,提问作者DejanS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:25:42