Как выполнить пакетное обновление в Snowflake JDBC

Я безуспешно пытаюсь выполнить пакетное обновление снежинки в PreparedStatement. Я могу выполнить каждый индивидуальный запрос (prepareStatement.executeQuery ()), чтобы запросы работали. Но как только я переключаюсь на batchUpdate (), я получаю исключение, которое, похоже, не устанавливает мои переменные (выбрасывается в insertEventStatement.executeBatch ()).

net.snowflake.client.jdbc.SnowflakeSQLException: SQL compilation error: error line 1 at position 134
Bind variable ? not set.
at net.snowflake.client.jdbc.SnowflakeUtil.checkErrorAndThrowException(SnowflakeUtil.java:88)
at net.snowflake.client.core.StmtUtil.execute(StmtUtil.java:384)
at net.snowflake.client.core.SFStatement.executeHelper(SFStatement.java:421)
at net.snowflake.client.core.SFStatement.executeQueryInternal(SFStatement.java:240)
at net.snowflake.client.core.SFStatement.executeQuery(SFStatement.java:180)
at net.snowflake.client.core.SFStatement.executeQuery(SFStatement.java:152)
at net.snowflake.client.core.SFStatement.execute(SFStatement.java:637)
at net.snowflake.client.jdbc.SnowflakeStatementV1.executeUpdateInternal(SnowflakeStatementV1.java:135)
at net.snowflake.client.jdbc.SnowflakePreparedStatementV1.executeBatch(SnowflakePreparedStatementV1.java:1045)

Кто-нибудь видит, что мне может не хватать?

public void insertBotEvents(List<SnowflakeRecord> snowflakeRecords) throws SQLException
{
    try
    {
        PreparedStatement insertEventStatement = connection.prepareStatement(INSERT_EVENT);
        PreparedStatement insertMetaEventStatement = connection.prepareStatement(INSERT_META_EVENT);
        for (SnowflakeRecord snowflakeRecord : snowflakeRecords)
        {
            insertEventStatement.setString(1, snowflakeRecord.getUserId());
            insertEventStatement.setString(2, snowflakeRecord.getSessionId());
            insertEventStatement.setString(3, snowflakeRecord.getEventTime().toString());
            insertEventStatement.setString(4, snowflakeRecord.getEventType());
            insertEventStatement.setString(5, snowflakeRecord.getEventValue());
            insertEventStatement.setString(6, snowflakeRecord.getAdditionalInfo());
            insertEventStatement.setString(7, snowflakeRecord.getAffiliateName());

            System.out.println("\nINSERTING NEW RECORD: \n" + snowflakeRecord);

            insertEventStatement.addBatch();

            if (snowflakeRecord.getSmVuiEventDto() != null && snowflakeRecord.getSmVuiEventDto().getParameters() != null)
            {
                for (ParametersDto parametersDto : snowflakeRecord.getSmVuiEventDto().getParameters())
                {

                    insertMetaEventStatement.setString(1, snowflakeRecord.getSmVuiEventDto().getName());
                    insertMetaEventStatement.setString(2, parametersDto.getName());
                    insertMetaEventStatement.setString(3, parametersDto.getValue());
                    insertMetaEventStatement.setString(4, snowflakeRecord.getUserId());
                    insertMetaEventStatement.setString(5, snowflakeRecord.getSessionId());
                    insertMetaEventStatement.setString(6, snowflakeRecord.getEventTime().toString());
                    insertMetaEventStatement.setString(7, snowflakeRecord.getEventType());
                    insertMetaEventStatement.setString(8, snowflakeRecord.getEventValue());
                    insertMetaEventStatement.setString(9, snowflakeRecord.getAdditionalInfo());

                    insertMetaEventStatement.addBatch();
                }
            }
        }
        insertEventStatement.executeBatch();
        insertMetaEventStatement.executeBatch();
        System.out.println("\nCommitting changes to snowflake.");
        connection.commit();
    }
    catch (Exception e)
    {
        connection.rollback();
        System.err.println("Unable to execute SQL. Rolling back snowflake import");
        e.printStackTrace();
        throw e;
    }

}

Вот вопросы:

private static final String INSERT_EVENT =
        "INSERT INTO EVENT " +
                "(USER_ID, " +
                " SESSION_ID, " +
                " EVENT_DATETIME, " +
                " EVENT_TYPE, " +
                " EVENT_VALUE, " +
                " ADDITIONAL_INFO, " +
                " AFFILIATE_ID " +
                ") " +
                "SELECT " +
                " ?, " +
                " ?, " +
                " ?, " +
                " ?, " +
                " ?, " +
                " ?, " +
                " AFFILIATE_ID " +
                "FROM AFFILIATE_LOOKUP " +
                "WHERE AFFILIATE_NAME = ?";

private static final String INSERT_META_EVENT =
        "INSERT INTO EVENT_META " +
        "(EVENT_ID, " +
        "   META_TYPE, " +
        "   META_NAME, " +
        "   META_VALUE " +
        ") " +
        "SELECT EVENT_ID, ?, ?, ? " +
        "FROM SM_VUI_EVENT " +
        "WHERE USER_ID=? AND " +
        "   SESSION_ID=? AND " +
        "   EVENT_DATETIME=? AND " +
        "   EVENT_TYPE=? AND " +
        "   EVENT_VALUE=? AND " +
        "   ADDITIONAL_INFO=?";

Изменить: по-видимому, он не был доступен в версии JDBC, которую я использовал (3.0.18), но был добавлен в недавнем выпуске (3.0.21). Я обновлю это дальше, если это не сработает.


person K. Wheeler    schedule 14.06.2017    source источник


Ответы (2)


Только что подтвердил, что Snowflake в настоящее время не поддерживает предоставление массива привязок в операторе INSERT, содержащем подзапрос, но мы работаем над этим.

person Howard Yu    schedule 17.06.2017
comment
Спасибо за информацию. Вы знаете, когда это планируется выпустить? В настоящее время я отправляю не так много данных. Но я ожидаю в ближайшее время большого количества данных, и, судя по результатам проведенных мною тестов, невозможно будет выполнить запросы по отдельности. Или есть способ лучше загрузить эти данные? - person K. Wheeler; 19.06.2017
comment
Он должен быть выпущен на следующей неделе. Однако реализация по-прежнему является циклом на стороне клиента и выполняется индивидуальный запрос. Если вы хотите загрузить большой объем данных, вам следует подумать о команде копирования. - person Howard Yu; 02.07.2017

Беглым взглядом ничего плохого не обнаружил. Можете ли вы связаться со службой поддержки Snowflake и предоставить свои журналы JDBC для трассировки?

Если вы не знаете, как включить ведение журнала, обратитесь к https://docs.snowflake.net/manuals/user-guide/jdbc-configure.html#configuring-logging.

Также, если вы можете предоставить свой идентификатор запроса, я могу быстро взглянуть.

person Howard Yu    schedule 15.06.2017