Liquibase importing sql files for mysql fails on multiple statements - mysql

I'm trying to start using Liquibase for a project that already has multiple SQL changelog files (that were previously maintained by hand). Using an advise from somewhere on stackoverflow I added a
<includeAll path="db/initial"/>
directive to my initial change log file, but it was failing with a not very useful
You have an error in your SQL syntax
message. Playing around I figured out that the problem is with multiple sql statements in the file. As long as I supplied a file with only one statement it worked.
So how do I tell Liquibase to execute multiple statements from an sql file?

A bit more searching to figure out that the problem is not with Liquibase but with MySql driver that by default refuses to execute multiple statements.
The key bit was to add allowMultiQueries=true to my connection string:
url: jdbc:mysql://localhost/test_project?allowMultiQueries=true

I would expected that you'd be using a sql_file refactoring to import a SQL file. It supports a "splitStatements" attribute that would solve your issue without the need to make changes to your JDBC settings.
The include statement is normally used to import liquibase changelogs.... Have you adapted your files to be formatted SQL changelogs? It would be well worth trying this out, I've included an example file:
Example
scottTiger.sql
--liquibase formatted sql
--changeset mark:1
CREATE TABLE BONUS (ENAME VARCHAR(10) NOT NULL, JOB VARCHAR(9) NOT NULL, SAL DECIMAL(7, 2), COMM DECIMAL(7, 2));
ALTER TABLE BONUS ADD CONSTRAINT BONUS_PK PRIMARY KEY (ENAME, JOB);
--rollback DROP TABLE BONUS;
--changeset mark:2
CREATE TABLE DEPARTMENT (DEPTNO INT NOT NULL, NAME VARCHAR(14), LOCATION VARCHAR(13), CONSTRAINT DEPT_PK PRIMARY KEY (DEPTNO));
--rollback DROP TABLE DEPARTMENT;
--changeset mark:3
CREATE TABLE EMPLOYEE (EMPNO INT NOT NULL, NAME VARCHAR(10), JOB VARCHAR(9), BOSS INT, HIREDATE VARCHAR(12), SALARY DECIMAL(7, 2), COMM DECIMAL(7, 2), DEPTNO INT, CONSTRAINT EMP_PK PRIMARY KEY (EMPNO));
ALTER TABLE PUBLIC.EMPLOYEE ADD CONSTRAINT BOSS_FK FOREIGN KEY (BOSS) REFERENCES PUBLIC.EMPLOYEE (EMPNO) ON UPDATE RESTRICT ON DELETE RESTRICT;
ALTER TABLE PUBLIC.EMPLOYEE ADD CONSTRAINT DEPARTMENT_FK FOREIGN KEY (DEPTNO) REFERENCES PUBLIC.DEPARTMENT (DEPTNO) ON UPDATE RESTRICT ON DELETE RESTRICT;
--rollback DROP TABLE EMPLOYEE;
--changeset mark:4
CREATE TABLE PROJECT (PROJECTNO INT NOT NULL, DESCRIPTION VARCHAR(100), START_DATE VARCHAR(12), END_DATE VARCHAR(12), CONSTRAINT PROJECT_PK PRIMARY KEY (PROJECTNO));
--rollback DROP TABLE PROJECT;
--changeset mark:5
CREATE TABLE ROLE (ROLE_ID INT NOT NULL, DESCRIPTION VARCHAR(100), CONSTRAINT ROLE_PK PRIMARY KEY (ROLE_ID));
--rollback DROP TABLE ROLE;
--changeset mark:6
CREATE TABLE PROJECT_PARTICIPATION (PROJECTNO INT NOT NULL, EMPNO INT NOT NULL, START_DATE VARCHAR(12) NOT NULL, END_DATE VARCHAR(12), ROLE_ID INT);
ALTER TABLE PROJECT_PARTICIPATION ADD CONSTRAINT PARTICIPATION_PK PRIMARY KEY (PROJECTNO, EMPNO, START_DATE);
ALTER TABLE PUBLIC.PROJECT_PARTICIPATION ADD CONSTRAINT EMPLOYEE_FK FOREIGN KEY (EMPNO) REFERENCES PUBLIC.EMPLOYEE (EMPNO) ON UPDATE RESTRICT ON DELETE RESTRICT;
ALTER TABLE PUBLIC.PROJECT_PARTICIPATION ADD CONSTRAINT PROJECT_FK FOREIGN KEY (PROJECTNO) REFERENCES PUBLIC.PROJECT (PROJECTNO) ON UPDATE RESTRICT ON DELETE RESTRICT;
ALTER TABLE PUBLIC.PROJECT_PARTICIPATION ADD CONSTRAINT ROLE_FK FOREIGN KEY (ROLE_ID) REFERENCES PUBLIC.ROLE (ROLE_ID) ON UPDATE RESTRICT ON DELETE RESTRICT;
--rollback DROP TABLE PROJECT_PARTICIPATION;
--changeset mark:7
CREATE TABLE SALARYGRADE (GRADE INT NOT NULL, LOSAL INT NOT NULL, HISAL INT NOT NULL, CONSTRAINT SALGRADE_PK PRIMARY KEY (GRADE));
--rollback DROP TABLE SALARYGRADE;
Note:
One thing I love about liquibase is its support for rollbacks.

Related

MySQL Error Code 1215: “Cannot add foreign key constraint”

I keep getting this error when attempting to create a table with SQL.
I have these two tables:
I'm using PHPMyAdmin and it won't allow me to use M_id as a foreign key which references Employee Table primary key E_id.
Anyone able to see what's wrong with my code?
Thanks!
Foreign key definitions have to exactly match the primary key columns to which they refer. In this case, you defined Department.M_id to a be a nullable integer column, while EMPLOYEE.E_id is integer not nullable. Try making M_id not nullable:
CREATE TABLE Department (
D_name VARCHAR(100) NOT NULL,
D_id INT NOT NULL,
M_id INT NOT NULL DEFAULT 0000,
...
FOREIGN KEY (M_id) REFERENCES EMPLOYEE(E_id)
ON DELETE SET DEFAULT ON UPDATE CASCADE
)
Your code has multiple errors:
varchar() length is too long.
You have a forward reference for a foreign key constraint.
SET DEFAULT doesn't really work.
You want something like this:
CREATE TABLE employees (
employee_id int not null primary key,
Job_type VARCHAR(100),
Ssn INT NOT NULL,
Salary DECIMAL NOT NULL,
Address VARCHAR(500) NOT NULL,
First_name VARCHAR(50) NOT NULL,
M_initial CHAR(1),
Last_name VARCHAR(50) NOT NULL,
E_end_date DATE,
E_start_date DATE NOT NULL,
department_id INT NOT NULL,
Super_id INT,
FOREIGN KEY (Super_id) REFERENCES employees(employee_id) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE (Ssn)
);
CREATE TABLE departments (
department_id int primary key,
D_name VARCHAR(100) NOT NULL,
D_id INT NOT NULL,
M_id INT DEFAULT 0000,
Manager_start_date DATE NOT NULL,
Manager_end_date DATE,
Report VARCHAR(8000),
Num_of_employees INT NOT NULL,
FOREIGN KEY (M_id) REFERENCES employees(employee_id) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE (D_name)
);
ALTER TABLE employees ADD CONSTRAINT FOREIGN KEY (department_id) REFERENCES departments(department_id)
ON DELETE CASCADE ON UPDATE CASCADE;
I also changed a few other things:
The table names are plural.
The primary keys are the singular form followed by "_id".
Foreign keys and primary keys have the same name.
The primary key is the first column in the table.
Here is a db<>fiddle showing that this works.
I will not question your design, though it looks problematic.
However - You cannot reference a table which doesn't exist yet (REFERENCES Department(D_id)). You should either remove the FOREIGN KEY constraints from the CREATE statements and add them afterwards in ALTER TABLE statements.
Example:
CREATE TABLE EMPLOYEE (...);
CREATE TABLE Department (...);
ALTER TABLE EMPLOYEE
ADD FOREIGN KEY (D_id)
REFERENCES Department(D_id)
ON DELETE CASCADE
ON UPDATE CASCADE
;
Demo
Or temporarily disable foreign key checks:
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE EMPLOYEE (...);
CREATE TABLE Department (...);
SET FOREIGN_KEY_CHECKS = 1;
Demo
You can also not use ON DELETE SET DEFAULT. InnoDB doesn't support it. You need to change it to ON DELETE SET NULL. If you want that behavior, you will need to implement it either in your application code or in a trigger.
I would also use TEXT as data type instead of VARCHAR(30000).

MySQL Error Code: 1824. Failed to open the referenced table

When I try to create the 'Project table I get this error Code: 1824. Failed to open the referenced table 'Employee'.
My syntax:
CREATE DATABASE IF NOT EXISTS Test;
USE Test;
CREATE TABLE IF NOT EXISTS Customer (
CustomerID VARCHAR(7) NOT NULL,
CustomerName VARCHAR(50),
CustAdress VARCHAR(70),
CustEmail VARCHAR(50),
PRIMARY KEY (CustomerID)
);
CREATE TABLE IF NOT EXISTS Employee (
EmpID VARCHAR(7) NOT NULL,
EmpName VARCHAR(50),
Position VARCHAR(30),
EmpTimePrice INT(4),
PRIMARY KEY (EmpID)
);
CREATE TABLE IF NOT EXISTS Project (
ProjectNo VARCHAR(7),
ProjectName VARCHAR(50),
StartDate DATE,
ProjTimePrice INT(6),
CustomerID VARCHAR(7),
EmpID VARCHAR(7),
PRIMARY KEY (ProjectNo),
FOREIGN KEY (EmpID) REFERENCES Employee (EmpID),
FOREIGN KEY (CustomerID) REFERENCES Customer (CustomerID)
);
CREATE TABLE IF NOT EXISTS ProjectWork (
ProjectNo VARCHAR(7),
EmpID VARCHAR(7),
PWDATE DATE,
HoursWorked INT(5),
FOREIGN KEY (ProjectNo) REFERENCES Project (ProjectNo),
FOREIGN KEY (EmpID) REFERENCES Employee (EmpID)
);
The names look correct to me and I have referenced the foreign key so I don't understand why I get this error. Any help would be appreciated, thanks.
This normally happens when the two tables have different Table engines. so check both tables if they have same table engines. for example MYISAM do not support Foreign Keys
Just edited EmpID to empID and it worked for some reason.
One of the easiest ways to get this error is referencing a table that doesn't exist yet. Eg if you run the following code on a new schema:
create table ttest (bob varchar(10) not null,
constraint fkbob foreign key (bob) references other(bob) );
... you will get the MySQL error:
Error Code: 1824. Failed to open the referenced table 'other'
Because the other table doesn't exist.
The code in the question above creates Employee before referencing it. However, note that the CREATE DATABASE and CREATE TABLE statements have IF EXISTS, but there are no DROP IF EXISTS statements, as when creating a new database. If you were debugging a table creation script, changing and fixing things as you go, it would have been pretty easy to get into an inconsistent state where the tables were out of synch with the code. This would also explain why other people could run the code cleanly, because these tables didn't exist in their schema yet.

Failed to open the referenced table

I am new with SQL and I am not entirely sure why I am getting the error: ERROR 1824 (HY000) at line 5: Failed to open the referenced table 'products'
Operation failed with exitcode 1
Here is my code
drop database if exists cc;
create database cc /*!40100 default character set utf8 */;
use cc;
create table Customers(
CustomerID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
prodID int,
quantity int,
primary key (CustomerID),
foreign key (prodID) references Products(itemID)
);
create table Employees(
EmployeeID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
ManagerID int not null,
primary key (EmployeeID),
foreign key (managerID) references Managers(mgrID)
);
create table Managers(
mgrID int not null,
salary float,
MaxSupervisingCapacity int,
foreign key (mgrID) references Employees(EmployeeID),
primary key (mgrID)
);
You can't create a foreign key that references another table until after you create that other table. In the Customers table you have
foreign key (prodID) references Products(itemID)
but there's no Products table yet. And in Employees you have
foreign key (managerID) references Managers(mgrID)
but the Managers table is created after it.
You need to reorder your table creations. Create Products before Customers.
Also, you can't have circular foreign key relationships. Employees.managerID references Managers and Managers.mgrID references Employees. This creates a chicken-and-egg problem: how would you create the first employee, since it needs a manager, but you can't create the first manager because it needs to refer to an employee.
You can solve this problem by allowing the foreign keys to be null. So you create the first employee with a null manager, then create the manager, then replace the managerID with this ID.
There's also a chicken-and-egg problem when creating these two tables. You can't reference a table that has yet to be created. So leave out the foreign key specification when creating the table, and add it later with ALTER TABLE.
create table Employees(
EmployeeID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
ManagerID int not null,
primary key (EmployeeID)
);
create table Managers(
mgrID int not null,
salary float,
MaxSupervisingCapacity int,
foreign key (mgrID) references Employees(EmployeeID),
primary key (mgrID)
);
alter table Employees add foreign key (managerID) references Managers(mgrID);
You can just surround the whole thing with a
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS;
SET FOREIGN_KEY_CHECKS=0;
## all of your schema and inserts
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
This change of the check will cause the engine not to do checks on those keys and just add them as is.
I have Just fixed this problem by Cheking both tables Storage Engine same and by settings the same Attributes for reff tables column.
you can try assigning the "ENGINE = INNODB" of the tables when creating them. One of the drawbacks when creating Foreign keys is that, the foreign keys can only be defined for certain storage engines (like InnoDB). The server accepts foreign key definitions for other storage engines but silently ignores them.
Example:
CREATE TABLE `Customers` (
CustomerID int not null,
FirstName varchar(255),
...
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
As you can see, when the table is finished, it is assigned the Engine = InnoDB and the default charset.
If you want to alter the table, you can do the following:
ALTER TABLE `Customers` ENGINE = InnoDB ;
If it served you, do not forget to approve the answer, you can make life easier for many developers.
I tried everything and nothing didn´t really work for me until I did the most simple thing. Go to SCHEMAS select the one that has de databases you are trying to work with and with right click, select set as default schema. That´s all, it worked perfectly.
Hope it helps

mySQL Deleteing Foreign Key

I have a database, I used these commands :
CREATE TABLE APPOINTMENT (app_id INT(5) NOT NULL, app_doctor INT(5) NOT NULL, app_date DATE, PRIMARY KEY (app_id));
CREATE TABLE APPPATIENTS (patient_ssn INT(10) NOT NULL, patient_name VARCHAR(20) NOT NULL, sex CHAR(1) NOT NULL, appointment_id INT(5), PRIMARY KEY (patient_ssn), UNIQUE (appointment_id));
ALTER TABLE APPPATIENTS ADD FOREIGN KEY (appointment_id) REFERENCES APPOINTMENT(app_id) ON DELETE CASCADE;
Now, I want to delete foreign key appointment_id in appPatients table :
ALTER TABLE apppatients DROP FOREIGN KEY appointment_id;
But I got an error :
Can't drop 'appointment_id'; check that column/key exists.
It is there! How can it give that error? What am I doing wrong?
I tried to create a database with your code and I notice the foreign key name appears different from appointment_id: reading with more attention the command definition, I notice that when you write
ADD FOREIGN KEY (appointment_id)
you are only saying the column on which the constraint will be created, not its name.
You can read the specifications here:
SQL FOREIGN KEY Constraint on ALTER TABLE
So, if you want to specify the name of the key, you have to write, for example:
alter table APPPATIENTS
ADD CONSTRAINT appointment_key
FOREIGN KEY (appointment_id)
REFERENCES appointment(app_id) ON DELETE CASCADE;
And so you know the name of the foreign key you created (appointment_key in this case).
If you want to know the foreign key name generated by mysql you can use the command
show create table APPPATIENTS;
that shows the complete table definition.

MySQL - Error Code 1215, cannot add foreign key constraint

i got these two succesfull queries:
create table Donors (
donor_id int not null auto_increment primary key,
gender varchar(1) not null,
date_of_birth date not null,
first_name varchar(20) not null,
middle_name varchar(20),
last_name varchar(30) not null,
home_phone tinyint(10),
work_phone tinyint(10),
cell_mobile_phone tinyint(10),
medical_condition text,
other_details text );
and
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id) );
but when i try this one:
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code),
foreign key(condition_code) references Donors_Medical_Condition(condition_code) );
i get "Error Code: 1215, cannot add foreign key constraint"
i dont know what am i doing wrong.
In MySql, a foreign key reference needs to reference to an index (including primary key), where the first part of the index matches the foreign key field. If you create an an index on condition_code or change the primary key st that condition_code is first you should be able to create the index.
To define a foreign key, the referenced parent field must have an index defined on it.
As per documentation on foreign key constraints:
REFERENCES tbl_name (index_col_name,...)
Define an INDEX on condition_code in parent table Donors_Medical_Condition and it should be working.
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
KEY ( condition_code ), -- <---- this is newly added index key
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id) );
But it seems you defined your tables order and references wrongly.
You should have defined foreign key in Donors_Medical_Condition table but not in Donors_Medical_Conditions table. The latter seems to be a parent.
Modify your script accordingly.
They should be written as:
-- create parent table first ( general practice )
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code)
);
-- child table of Medical_Conditions
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id),
foreign key(condition_code)
references Donors_Medical_Condition(condition_code)
);
Refer to:
MySQL Using FOREIGN KEY Constraints
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION
A workaround for those who need a quick how-to:
FYI: My issue was NOT caused by the inconsistency of the columns’ data types/sizes, collation or InnoDB storage engine.
How to:
Download a MySQL workbench and use it’s GUI to add foreign key. That’s it!
Why:
The error DOES have something to do with indexes. I learned this from the DML script automatically generated by the MySQL workbench. Which also helped me to rule out all those inconsistency possibilities.It applies to one of the conditions to which the foreign key definition subject. That is: “MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan.” Here is the official statement: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html
I did not get the idea of adding an index ON the foreign key column(in the child table), only paid attention to the referenced TO column(in the parent table).
Here is the auto-generated script(PHONE.PERSON_ID did not have index originally):
ALTER TABLE `netctoss`.`phone`
ADD INDEX `personfk_idx` (`PERSON_ID` ASC);
ALTER TABLE `netctoss`.`phone`
ADD CONSTRAINT `personfk`
FOREIGN KEY (`PERSON_ID`)
REFERENCES `netctoss`.`person` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
I think you've got your tables a bit backwards. I'm assuming that Donors_Medical_Condtion links donors and medical conditions, so you want a foreign key for donors and conditions on that table.
UPDATED
Ok, you're also creating your tables in the wrong order. Here's the entire script:
create table Donors (
donor_id int not null auto_increment primary key,
gender varchar(1) not null,
date_of_birth date not null,
first_name varchar(20) not null,
middle_name varchar(20),
last_name varchar(30) not null,
home_phone tinyint(10),
work_phone tinyint(10),
cell_mobile_phone tinyint(10),
medical_condition text,
other_details text );
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code) );
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id),
foreign key(condition_code) references Medical_Conditions(condition_code) );
I got the same issue and as per given answers, I verified all datatype and reference but every time I recreate my tables I get this error. After spending couple of hours I came to know below command which gave me inside of error-
SHOW ENGINE INNODB STATUS;
LATEST FOREIGN KEY ERROR
------------------------
2015-05-16 00:55:24 12af3b000 Error in foreign key constraint of table letmecall/lmc_service_result_ext:
there is no index in referenced table which would contain
the columns as the first columns, or the data types in the
referenced table do not match the ones in table. Constraint:
,
CONSTRAINT "fk_SERVICE_RESULT_EXT_LMC_SERVICE_RESULT1" FOREIGN KEY ("FK_SERVICE_RESULT") REFERENCES "LMC_SERVICE_RESULT" ("SERVICE_RESULT") ON DELETE NO ACTION ON UPDATE NO ACTION
I removed all relation using mysql workbench but still I see same error. After spending few more minutes, I execute below statement to see all constraint available in DB-
select * from information_schema.table_constraints where
constraint_schema = 'XXXXX'
I was wondering that I have removed all relationship using mysql workbench but still that constraint was there. And the reason was that because this constraint was already created in db.
Since it was my test DB So I dropped DB and when I recreate all table along with this table then it worked. So solution was that this constraint must be deleted from DB before creating new tables.
Check that both fields are the same size and if the referenced field is unsigned then the referencing field should also be unsigned.