如何向Spark参数化查询传递null值?
如何向Spark SQL参数化查询传递null值?
我尝试使用Spark SQL的参数化查询,但传递None作为参数时出现错误。
我的代码如下:
def create_table(): spark.sql("create table test_nulls(val string, description string)") def test_nulls(val: str, description: str): spark.sql(f"insert into test_nulls(val, description) values ({val}, {description})", val=val, description=description) create_table() test_nulls("some_val", "some_description") test_nulls("some_val", None)
我期望第二次调用test_nulls()时执行类似insert into test_nulls(val, description) values('some_val', null)的SQL语句,但执行失败并报错:
[UNRESOLVED_COLUMN.WITH_SUGGESTION] A column or function parameter with name 'None' cannot be resolved. ; line 1 pos 60; 'InsertIntoStatement 'UnresolvedRelation [test_nulls], [], false, [val, description], false, false, false, +- 'UnresolvedInlineTable [col1, col2], [[some_val, 'None]]
问题原因
你错误地将f-string字符串拼接和Spark的参数化查询混用了。f-string会先把Python的None转换成字符串"None",最终生成的SQL语句里会出现values (some_val, None),Spark会把这里的None当成列名,因此抛出无法解析列的错误。
解决方案
直接使用Spark SQL的参数化占位符,不要用f-string拼接SQL:
方式1:命名参数占位符
def create_table(): spark.sql("create table test_nulls(val string, description string)") def test_nulls(val: str, description: str): # 直接使用命名占位符,由Spark处理参数替换 spark.sql( "insert into test_nulls(val, description) values ({val}, {description})", val=val, description=description ) create_table() test_nulls("some_val", "some_description") test_nulls("some_val", None)
方式2:位置占位符(?)
如果偏好按顺序传递参数,可以用?作为占位符:
def test_nulls(val: str, description: str): spark.sql( "insert into test_nulls(val, description) values (?, ?)", (val, description) )
说明
- 当传递Python的
None时,Spark会自动将其映射为SQL标准的NULL值,不需要手动处理。 - 使用Spark原生的参数化查询不仅能正确处理null值,还能避免SQL注入风险,同时Spark会自动处理字符串类型参数的单引号包裹,无需手动添加。
内容的提问来源于stack exchange,提问作者archjkeee
相关产品推荐
相关产品推荐

