4

I have the Problem that I want Docker Compose to directly import my Database.sql file after setting up MySQL. But it always throws me the Error:

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 'DELIMITER |' at line 1

But somehow when I import it through phpMyAdmin in Browser it works perfectly fine.

This is my docker-compose.yml:

version: "3.2"
services:
  php:
    build: './php/'
    networks:
      - backend
    volumes:
      - ./www/:/var/www/html/
  apache:
    build: './apache/'
    depends_on:
      - php
      - mysql
    networks:
      - frontend
      - backend
    ports:
      - "8081:80"
    volumes:
      - ./www/:/var/www/html/
  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/tmp/database
    command: mysqld --max_allowed_packet=32505856 --user=root --init-file="/tmp/database/schema.sql"
    networks:
      - backend
    environment:
      - MYSQL_ROOT_PASSWORD=root
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    links:
        - mysql
    ports:
      - '8082:80'
    environment:
      MYSQL_USERNAME: root
      MYSQL_ROOT_PASSWORD: root
      PMA_HOST: mysql
    networks:
      - backend
networks:
  frontend:
  backend:

This is an Example Snippet of my .sql File which gets executed:

-- phpMyAdmin SQL Dump
-- version 4.8.2
-- https://www.phpmyadmin.net/
--
-- Host: mysql
-- Generation Time: Aug 20, 2018 at 08:30 AM
-- Server version: 5.7.23
-- PHP Version: 7.2.6
DELIMITER $$

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";

--
-- Database: `database`
--
CREATE DATABASE IF NOT EXISTS `databasetest` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `databasetest`;

--
-- Procedures
--
DROP PROCEDURE IF EXISTS `sp_filestatus_get`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_filestatus_get` (IN `filename_name` VARCHAR(500), IN `kampagne_name` VARCHAR(100), IN `outlet_name` VARCHAR(100))  NO SQL

... Some more stuff

END;

Did I miss something in the configuration? Or why doesnt it work with compose but directly in phpMyAdmin it works?

  • 1
    Please keep in mind that `DELIMITER` is not a MySQL command. It's a command that your MySQL client needs to support. So probably docker (or your version of docker) somehow doesn't support it. – Ildar Akhmetov Aug 17 '18 at 08:41
  • Ah thanks for the response I didnt know that. Thats why it works directly in phpMyAdmin. Is there any possibility to find out which Docker Version supports DELIMITER? –  Aug 17 '18 at 08:45
  • I have no idea, unfortunately, never worked with Docker. Just faced this issue with other clients. – Ildar Akhmetov Aug 17 '18 at 09:30

3 Answers3

1

The DELIMETER isn't supported by sql API directly, since the support of the statement is defined by the client it works in phpmyadmin, because it supports that. The default mysql client uses delimeter statement, follow suggested steps in the Stored programs defining and update the sql file accordingly ( The CREATE PROCEDURE shall be replaced with your sql statements).

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)
    -> BEGIN
    ->   SET @x = 0;
    ->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

According to the script you are using, you have to handle the delimeter differently, than it is now:

Replace

DROP PROCEDURE IF EXISTS `sp_filestatus_get`$$

to

DROP PROCEDURE IF EXISTS `sp_filestatus_get`;

Also, please replace END; to END $$ and add DELIMITER ; at the end of file.

Here is some links which shall be use full for you in finding things to adjust in the init sql script:

Andriy Ivaneyko
  • 20,639
  • 6
  • 60
  • 82
  • So in fact I have to set the delimiter with command line? Something like that: `command: mysqld delimiter $$ --max_allowed_packet=32505856 --user=root --init-file="/tmp/database/winwin_pms_schema.sql"`. $$ Because all my Statements use `DELIMITER $$`. Its just an idea because this command doesnt work –  Aug 20 '18 at 09:43
  • nope, it shall be defined in top of `winwin_pms_schema.sql` and after the END of defining sql procedure set back to previous value (`;`) – Andriy Ivaneyko Aug 20 '18 at 09:45
  • @reiner.luke Also, I bet it's sql related problem than docker-compose – Andriy Ivaneyko Aug 20 '18 at 09:46
  • Edited my Question guys. As you can see there I define Delimiter at top of all Statements and reset it at `END;`. But still same error. –  Aug 20 '18 at 09:52
  • thank you for your update. This is the right answer with much information. Ill reward you in 23 hours. –  Aug 20 '18 at 09:58
  • 1
    @reiner.luke you are welcome, good luck ! :) Thank you for rewarding! – Andriy Ivaneyko Aug 20 '18 at 09:59
  • Just to clarify for other users: this question gets the bounty for details and information and the other question get the accepted answer because at the moment its the fast hot fix I searched for. –  Aug 20 '18 at 14:33
0

If you really need your DELIMITER statement, you could change your command for mysql to

bash -c "service mysql start && echo 'xxxxxxxxxxxxxxxxx' && mysql --max_allowed_packet=32505856 -u root -proot < /tmp/database/schema.sql && while true; do sleep 1; done"

then it should work without any other change.

So your mysql-section should look like this:

  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/tmp/database
    command: bash -c "service mysql start && echo 'xxxxxxxxxxxxxxxxx' && mysql --max_allowed_packet=32505856 -u root -proot < /tmp/database/schema.sql && while true; do sleep 1; done"
    networks:
      - backend
    environment:
      - MYSQL_ROOT_PASSWORD=root

Explanation why it works:

Before, you were starting the mysql-server using the mysqld command and specifying the init-script. Now it is started as a service. This brings one advantage and one disadvantage.

  • Advantage: You can now connect to your mysql-server using mysql command.
  • Disadvantage: After you've specified the mysql command, the container will be stopped by docker.

To handle the disadvantage, I've added while true; do sleep 1; done as last command. This causes the container to run until it gets stopped. The echo ist just for you to see that the commands get executed.

Halko Karr-Sajtarevic
  • 2,248
  • 1
  • 16
  • 14
  • 1
    doesnt work. It doesnt even try to execute my sql file. –  Aug 20 '18 at 12:21
  • I'm sorry - fixed the issues! – Halko Karr-Sajtarevic Aug 20 '18 at 12:46
  • Damn it worked. Please explain why it works so this can be the rewarded answer. This is way more shorter and easier then the answer before! And it just does what I asked for. Im sorry for the guy who downvoted –  Aug 20 '18 at 12:57
  • 1
    PS: Grüße aus Österreich :D –  Aug 20 '18 at 13:05
  • @HalkoKarr-Sajtarevic you can do whatever you want, but keep in mind that you are doing work around here instead of addressing root cause of the problem, which is definitely not are pros for both of you ... Good luck guys ! – Andriy Ivaneyko Aug 20 '18 at 13:06
  • @AndriyIvaneyko can you explain in detail whats going on here or why that workaround is not safe? –  Aug 20 '18 at 13:12
  • 1
    @reiner.luke well, it comes from reasoning, you have syntax error in the sql, and fix it the way you carry that script, that's explicit... Also, you have to careful here because I guess you may have silent exception, during execution of the mysql command, which not raised, and the container keeps running because you have added `while` loop. You can double check sql service start logs for that and make sure that running your script in interactive session won't raise exception. Regarding safety: workaround != unsafe... – Andriy Ivaneyko Aug 20 '18 at 13:30
  • @reiner.luke please let me know if something not clear for you, so I will try to give more information... – Andriy Ivaneyko Aug 20 '18 at 14:18
  • @andriyivaneyko: i don't think it is a "workaround" - reiner.luke was starting the server using mysqld command - and that's not good either. the image provides the mysql-server as a service - so why not use it... – Halko Karr-Sajtarevic Aug 20 '18 at 15:10
  • updated my answer with a short explanation - hope it's clearer now – Halko Karr-Sajtarevic Aug 20 '18 at 15:17
0

think I might have stumbled onto a less hacky solution by using /docker-entrypoint-initdb.d/ instead of the init-file=... flag:

docker-compose.yml
  db:
    image: "mysql:5.7.33"
    container_name: "mydb"
    command: "--default-authentication-plugin=mysql_native_password"
    volumes: # Scripts will apparently be executed by ascending order. See https://github.com/docker-library/mysql/issues/395#issuecomment-375409393
    - db-datavolume:/var/lib/mysql
    - ./db/init.sql:/docker-entrypoint-initdb.d/init1.sql
    - ./db/triggers.sql:/docker-entrypoint-initdb.d/init2.sql
    - ./db/seed.sql:/docker-entrypoint-initdb.d/init3.sql
  ...

volumes:
  db-datavolume

After that, in the host machine's ./db/triggers.sql (which mounts to /docker-entrypoint-initdb.d/init2.sql), DELIMETER works just fine.

Michael Bluth
  • 121
  • 1
  • 6