Как исправить синтаксическую ошибку SQL, используя liquibase и mysql для создания триггера

Я настраиваю первый проект Liquibase Maven для БД MySQL. До создания триггеров все в порядке.

Я считаю, что это проблема с liquibase и JDBC, которые неправильно обрабатывают SQL с несколькими операторами, но я не могу понять, чего мне не хватает.

Вот мои зависимости pom

    <dependency>
      <groupId>org.liquibase</groupId>
      <artifactId>liquibase-parent</artifactId>
      <version>3.5.3</version>
      <type>pom</type>
    </dependency>

    <dependency>
      <groupId>org.liquibase</groupId>
      <artifactId>liquibase-core</artifactId>
      <version>3.5.3</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.46</version>
    </dependency>

    <dependency>
      <groupId>org.liquibase</groupId>
      <artifactId>liquibase-maven-plugin</artifactId>
      <version>3.6.3</version>
    </dependency>

Это мой включаемый файл Liquibase

<databaseChangeLog xmlns = "http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation = "http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">

  <changeSet id = "event_horizon_1_0_0" author = "lmtyler" dbms = "mysql">
    <sql>
      drop trigger if exists ai_event_approval;
    </sql>
  </changeSet>

  <changeSet id = "event_horizon_1_0_1" author = "lmtyler" dbms = "mysql">
    <sqlFile splitStatements = "false" stripComments = "false" endDelimiter = "DONE" path = "01__ai_event_approval.sql" relativeToChangelogFile = "true" />
  </changeSet>

</databaseChangeLog>

Это мой файл sql

CREATE DEFINER ='evclient'@'%' TRIGGER ai_event_approval
    AFTER INSERT
    ON event_approval
    FOR EACH row
begin
    insert into event_approval_log (rowAction,
                                    actionTs,
                                    event,
                                    requestorEmail,
                                    requestReason,
                                    statusType,
                                    approverUserId,
                                    approverReason,
                                    lastChangTs)
        values ('I',
                current_timestamp(6),
                new.event,
                new.requestorEmail,
                new.requestReason,
                new.statusType,
                new.approverUserId,
                new.approverReason,
                new.lastChangTs);
end;
# DONE

Я ожидал, что, установив splitStatements, stripComments и endDelimiter, я заставлю liquibase отправлять весь SQL как один через JDBC.

Но я получаю эту ошибку

[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.6.3:update (default) on project event-horizon-mysql: Error setting up or running Liquibase: Migration failed for change set /Users/lmtyler/OneDrive - Walmart Inc/workspace/code/event-horizon/event-horizon-mysql/src/main/java/resources/liquibase/schema/triggers/02__au_event_approval.sql::event_horizon_1_0_1::lmtyler:
[ERROR]      Reason: liquibase.exception.DatabaseException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 23 [Failed SQL: CREATE TRIGGER au_event_approval
[ERROR]     AFTER UPDATE
[ERROR]     ON event_approval
[ERROR]     FOR EACH row
[ERROR] begin
[ERROR]     insert into event_approval_log (rowAction,
[ERROR]                                     actionTs,
[ERROR]                                     event,
[ERROR]                                     requestorEmail,
[ERROR]                                     requestReason,
[ERROR]                                     statusType,
[ERROR]                                     approverUserId,
[ERROR]                                     approverReason,
[ERROR]                                     lastChangTs)
[ERROR]     values ('U',
[ERROR]             current_timestamp(6),
[ERROR]             new.event,
[ERROR]             new.requestorEmail,
[ERROR]             new.requestReason,
[ERROR]             new.statusType,
[ERROR]             new.approverUserId,
[ERROR]             new.approverReason,
[ERROR]             new.lastChangTs)]

Может быть, это поможет, если вы позволите Liquibase работать с updateSQL вместо update. Тогда liquibase не будет запускать изменения непосредственно в БД, а выведет их на стандартный ввод. Таким образом, вы можете проверить, как анализируется ваш файл sql.

Jens 19.07.2019 11:48

@Jens Спасибо за предложение! Изменено на updateSQL проверенный выходной файл. Они выдали правильные результаты SQL ... new.lastChangTs); end;, но когда я возвращаюсь к update, он снова усекает ; end; из SQL и получает ту же ошибку, что и выше.

Mike 19.07.2019 14:39

Прохладный. Возможно, тогда это проблема на стороне JDBC. Вы можете попробовать использовать allowMultiQueries=true в своей конфигурации для соединения JDBC.

Jens 19.07.2019 14:53
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
3
3
2 329
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ночной сон вместе с предложением @Jens Я наконец вижу проблему.

Во-первых, если вы видите мой пост, ошибка была не для SQL, как я думал. Я думал, что это AFTER INSERT выдает ошибку, но это был AFTER UPDATE

Ключ был в том, чтобы установить splitStatements:false, установка endDelimiter не требовалась.

Вот два работающих примера:

<changeSet id = "event_horizon_1_0_1" author = "lmtyler" dbms = "mysql">
    <sqlFile splitStatements = "false" stripComments = "false" path = "01__ai_event_approval.sql" relativeToChangelogFile = "true"/>
</changeSet>

с этим файлом sql

CREATE DEFINER ='evclient'@'%' TRIGGER ai_event_approval
    AFTER INSERT
    ON event_approval
    FOR EACH row
begin
    insert into event_approval_log (rowAction,
                                    actionTs,
                                    event,
                                    requestorEmail,
                                    requestReason,
                                    statusType,
                                    approverUserId,
                                    approverReason,
                                    lastChangTs)
        values ('I',
                current_timestamp(6),
                new.event,
                new.requestorEmail,
                new.requestReason,
                new.statusType,
                new.approverUserId,
                new.approverReason,
                new.lastChangTs);
end;

А вот с использованием формата SQL

--changeset lmtyler:event_horizon_1_0_1 dbms:mysql splitStatements:false
CREATE TRIGGER au_event_approval
    AFTER UPDATE
    ON event_approval
    FOR EACH row
begin
    insert into event_approval_log (rowAction,
                                    actionTs,
                                    event,
                                    requestorEmail,
                                    requestReason,
                                    statusType,
                                    approverUserId,
                                    approverReason,
                                    lastChangTs)
    values ('U',
            current_timestamp(6),
            new.event,
            new.requestorEmail,
            new.requestReason,
            new.statusType,
            new.approverUserId,
            new.approverReason,
            new.lastChangTs);
end;

У меня возникла та же проблема при выполнении триггера внутри тега SQL. Если вы выполняете блок кода в liquibase, не забудьте добавить splitStatements: false к тегу SQL.

<changeSet id = "your_id" author = "your_name">

    <comment>your comments</comment>

    <sql splitStatements = "false">
        CREATE TRIGGER trigger_name
        BEFORE UPDATE ON table_name FOR EACH ROW
        BEGIN
        --Your Code Block
        END;
    </sql>
</changeSet>

Другие вопросы по теме