Google BigQuery,在准备好的语句中为空值引发异常

Posted

技术标签:

【中文标题】Google BigQuery,在准备好的语句中为空值引发异常【英文标题】:Google BigQuery, Exception thrown for null value in prepared statement 【发布时间】:2021-03-10 21:55:26 【问题描述】:

我们正在尝试使用 Jdbc(Simba 驱动程序)将数据加载到 google bigquery。当尝试在准备好的语句中插入空值时,我们遇到了异常。这在它不是准备好的语句时有效。例如代码(隐藏连接Url):

import java.sql.*;

public class Program 

    public static void main(String[] args) 
        Program program = new Program();
        try 
            program.doStatement();
         catch (Exception e) 
            e.printStackTrace();
        
        try 
            program.doPreparedStatement();
         catch (Exception e) 
            e.printStackTrace();
        

    

   

    public Program() 

    public void doPreparedStatement() throws Exception 
         try(Connection connection = getConnection()) 
            
            PreparedStatement statement = connection.prepareStatement("INSERT INTO test1.my_table (CONTACT, COMPANY, ADDRESS, CITY, STATE, ZIP) VALUES (?,?,?,?,?,?)");
            statement.setString(1, "MyContact");
            statement.setString(2, "MyCompany");
            statement.setString(3, "MyAddress");
            statement.setString(4, "MyCity");
            statement.setString(5, "MyState");
            statement.setNull(6, Types.BIGINT);
            System.err.println("Executing prepared statement...");
           int count = statement.executeUpdate();
        
        System.err.println(" done.");
    

    public void doStatement() throws Exception 
        try(Connection connection = getConnection()) 
            String create_command = 
                "CREATE TABLE test1.my_table ( CONTACT STRING, COMPANY STRING, ADDRESS STRING, CITY STRING, STATE STRING, ZIP STRING )";
            Statement createStatement = connection.createStatement( );
            System.err.println("Create table.");
            createStatement.execute(create_command);
            System.err.println("Table created.");
            
            System.err.println("Executing statement...");
            Statement statement = connection.createStatement();
            int count = statement.executeUpdate("INSERT INTO test1.my_table (CONTACT, COMPANY, ADDRESS, CITY, STATE, ZIP) VALUES ('MyContact','MyCompany','MyAddress','MyCity','MyState',NULL)");
        
        System.err.println(" done.");
    

    private Connection getConnection() throws Exception
    
        Connection connection = null;
        connection = DriverManager.getConnection(CONNECTION_URL);
        return connection;
    



产生以下输出:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Create table.

Table created.

Executing statement...

 done.

Executing prepared statement...

java.sql.SQLException: [Simba][BigQueryJDBCDriver](100032) Error executing query job. Message: Unparseable query parameter `` in type `TYPE_INT64`, Bad int64 value: null value: 'null'
        at com.simba.googlebigquery.googlebigquery.client.BQClient.insertJob(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.client.BQClient.executeQuery(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.dataengine.BQAbstractExecutor.execute(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.dataengine.BQSQLExecutor.execute(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeWithParams(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeAnyUpdate(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeUpdate(Unknown Source)
        at Program.doPreparedStatement(Program.java:35)
Caused by: com.simba.googlebigquery.support.exceptions.GeneralException: [Simba][BigQueryJDBCDriver](100032) Error executing query job. Message: Unparseable query parameter `` in type `TYPE_INT64`, Bad int64 value: null value: 'null'
        ... 8 more

【问题讨论】:

【参考方案1】:

我发现在将 BigQuery 支持添加到 jOOQ(例如,请参阅 #11841)时,对于数字类型可以使用:

statement.setBigDecimal(6, null);

BigDecimal 类型是唯一非原始的数字 JDBC 类型。对于其他数据类型,如果支持,请使用它们各自的 setter,或者 setString(6, null),如果 Simba 仍然不喜欢相应类型的 NULL 值,包括例如:

Boolean Date Time

如果对任何转换问题有疑问(例如,因为 Simba 似乎将 BigDecimal 绑定为 STRING,目前至少在版本 1.2.13.1016 中),请确保您强制转换绑定变量,例如:

CAST(? AS INT64)

【讨论】:

以上是关于Google BigQuery,在准备好的语句中为空值引发异常的主要内容,如果未能解决你的问题,请参考以下文章

java - 如何在java中为mysql的JSON数据类型使用准备好的语句?

如何在 Google bigquery 中为多个动态表创建授权视图?

在 PHP 中为 MATCH AGAINST 准备的语句不起作用

限制最大准备好的语句计数

Google 数据准备 - 无法从 BigQuery 导入表(从 Google 表格创建)“未找到”

sql 脚本适用于 MySQL,但不适用于 google bigquery