无法通过Google Spanner JDBC驱动将Spark DataFrame写入Spanner表
解决Spark写入Spanner JDBC时的语法错误
问题场景
使用Spark DataFrame向Google Spanner数据库写入数据时触发语法错误,相关信息如下:
写入代码
data.write.format("jdbc") .option("url", jdbcUrl) .option("driver", "com.google.cloud.spanner.jdbc.JdbcDriver") .option("dbtable", tableName) .mode("append") .save()
DataFrame Schema
root |-- sampleNumber: string (nullable = true)
目标表Schema
|-- sampleNumber: string (nullable = true)
报错信息
Caused by: repackaged.com.google.google.cloud.spanner.SpannerBatchUpdateException: Syntax error: Unexpected string literal \"sampleNumber\" [at 1:37]\nINSERT INTO Account (\"sampleNumber\") VALUES (@p1)\n ^ at repackaged.com.google.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.batchException(JdbcSqlExceptionFactory.java:325)
错误原因
报错显示生成的INSERT语句用双引号包裹了列名"sampleNumber",但Spanner的Google SQL方言不支持这种语法:
- Spanner中双引号仅用于引用包含特殊字符或需区分大小写的标识符,普通列名无需包裹
- Spark JDBC驱动默认会给列名添加双引号,导致Spanner解析SQL时触发语法错误
解决方案
方案1:禁用JDBC驱动的列名引号
在写入配置中添加quote选项并设为空字符串,阻止驱动给列名添加双引号:
data.write.format("jdbc") .option("url", jdbcUrl) .option("driver", "com.google.cloud.spanner.jdbc.JdbcDriver") .option("dbtable", tableName) .option("quote", "") // 禁用列名引号包裹 .mode("append") .save()
方案2:手动构造兼容Spanner的INSERT语句
如果方案1不生效,直接用query选项指定符合Spanner语法的INSERT语句,列名不添加任何引号:
val insertQuery = s"INSERT INTO Account (sampleNumber) VALUES (?)" data.write.format("jdbc") .option("url", jdbcUrl) .option("driver", "com.google.cloud.spanner.jdbc.JdbcDriver") .option("query", insertQuery) .mode("append") .save()
补充说明
Spanner的Google SQL方言中,普通标识符(列名、表名)默认大小写不敏感,无需用引号包裹;仅当标识符包含特殊字符或需要强制区分大小写时,才使用反引号(`)包裹标识符。
内容的提问来源于stack exchange,提问作者user22427575
相关产品推荐
相关产品推荐

