flyway create table migration if already exists - mysql

I have a create table migration, I had to run flyway repair and because that table already exists in database I can't perform flyway migrate , it fails with
Caused by: java.sql.SQLSyntaxErrorException: Table 'TABLE_NAME' already exists
error message.
Is there any way to fix it without dropping database ? Since it already was populated with data.

I ended up creating those rules for creating a migration:
If creating a new table, always use IF NOT EXISTS (thank to #ShaharT 's advice)
CREATE TABLE IF NOT EXISTS table_name(
--params
);
When altering a TABLE
We are declaring a procedure that can handle the 1060 MySQL error (column already exists) and adding ALGORITHM and LOCK arguments.
delimiter ;;
DROP PROCEDURE IF EXISTS alterNoFailure;;
create procedure alterNoFailure ()
begin
declare continue handler for 1060 begin end;
ALTER TABLE table_name
ADD COLUMN column_name double DEFAULT 0 NOT NULL,ALGORITHM=INPLACE, LOCK=NONE;
end;;
call alterNoFailure();;
You can specify multiple ALTER queries inside the procedure

Related

Create Trigger inside stored procedure in mysql

I want to create an trigger inside an procedure. but after some research I got to know that it is not possible. can u suggest me another way I can achieve the below actions. (I cant share exact data and queries due to some reason. please refer similar queries.)
What I want
I have created an temporary table containing data i need.
eg. CREATE TEMPORARY TABLE temp1 SELECT id, col_1 FROM table1 WHERE col_1=2;
I want to inset data in table table2 when data is inserted in temp1, which i can achieve by creating a TRIGGER. but the problem is I want to give a value in table2 which will be dynamic and will be taken from nodejs backend. so i created a PROCEDURE which takes parameter neededId. but i cant created trigger inside a procedure. is their any other way i can achieve this?
Procedure I Created
here neededId is the foreign key I get from backend to insert
DELIMITER $$
USE `DB`$$
CREATE PROCEDURE `MyProcedure` (IN neededID int)
BEGIN
DROP TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1 SELECT id, col_1 FROM table1 WHERE col_1=2;
DROP TRIGGER IF EXISTS myTrigger;
CREATE TRIGGER myTrigger AFTER INSERT ON temp1 FOR EACH ROW
BEGIN
INSERT into table2("value1", "value2", neededId);
END;
END$$
DELIMITER ;
SQL Statements Not Permitted in Stored Routines
Generally, statements not permitted in SQL prepared statements are also not permitted in stored programs. ... Exceptions are SIGNAL, RESIGNAL, and GET DIAGNOSTICS, which are not permissible as prepared statements but are permitted in stored programs.
SQL Syntax Permitted in Prepared Statements
CREATE TRIGGER is not listed.
Finally: the trigger cannot be created in stored procedure, function, prepared statement, trigger or event procedure.
In MySQL, you can't create a trigger for a temporary table, regardless of whether you do it in a stored procedure or not.
https://dev.mysql.com/doc/refman/8.0/en/create-trigger.html says:
The trigger becomes associated with the table named tbl_name, which must refer to a permanent table. You cannot associate a trigger with a TEMPORARY table or a view.
I assume the same is true of MariaDB. It's not clear from your question which one you use. You say MySQL at first, but you tagged the question mariadb. Be aware that these are not the same database product, and they are not necessarily compatible.
Here's a demo of the error, tested on MySQL 8.0.28:
mysql> create temporary table t ( i int );
mysql> create trigger t before insert on t for each row set NEW.i = 42;
ERROR 1361 (HY000): Trigger's 't' is view or temporary table
So in your case, you cannot use a trigger for the temporary table. You'll have to think of a different way to implement inserts to your second table.

Error when Updating a Table with Trigger

I have a trigger setup that every time a new table is created, it reads the ID (which is in varchar) and converts it to integer and stores it in another column.
However when I run it I encounter the following error:
Can't update table 'products' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
This is my trigger:
CREATE TRIGGER `var_to_int` AFTER INSERT ON `products`
FOR EACH ROW UPDATE `products`
SET `int_id`= CAST(`var_id` AS INT)
WHERE `int_id` IS NULL OR `int_id` = ''
How do I prevent this?
This error is thrown by the PHP script creating a new item in the table.
You can not update the table itself.
Trigger starts when it is UPDATE, and then it has to do UPDATE. An endless loop is formed. Try using an additional table to store temporary data to later update the correct table

MySQL - Drop temporary table when exception occurs in a stored procedure

I am new to MySQL and not able to figure out how to drop all temporary table created within stored procedure when any exception occurs. The problem is when error occurs on first call of stored procedure and if I try to call procedure again it throws exception like "temporary table already exists".
I can use DROP TEMPORARY TABLE IF Exits [tablename] syntax and than create temporary table again, but i think its not the best solution. Is there any way to drop all temporary tables when any SQL exception occurs in the procedure?
Following is what I am trying to drop temporary tables but I am getting error
Error Code: 1051 Unknown table '[databasename].testtable'
Code:
CREATE DEFINER=`*****`#`%` PROCEDURE `Test`()
BEGIN
DECLARE CONTINUE HANDLER FOR sqlexception
BEGIN
DROP TEMPORARY TABLE TestTable;
END;
CREATE TEMPORARY TABLE TestTable AS SELECT * FROM
(
(SELECT 1 AS AccountID)
UNION
(SELECT 2 AS AccountID)
) bt;
SELECT
*
FROM
TestTable;
SIGNAL SQLSTATE '45000' SET message_text = 'test';
DROP TEMPORARY TABLE TestTable;
END

In memory table and temp table in MySql

I am looking for Sql-Server relevant feature in MySql
Table variable inside procedure. here
Temporary Table inside procedure. here
I hope the table variables are in-memory and temporary tables are stored in temp database.
If both declared inside procedure, both will be cleaned after the procedure finished its execution.
MySql provides only one option called Temporary Table. How to achieve these two? and do we need to clear those tables or MySql will take care of it after the procedure completed?
From MySQL documentation:
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name.
More info: http://dev.mysql.com/doc/refman/5.1/en/create-table.html#create-temporary-table
But what happens if I'm using a single connection? May be you will have some data conflicts. In the past I use temporary tables with a unique id to avoid conflicts if I call the procedure with the same connection more than one time:
DELIMITER $$
DROP PROCEDURE some_proc $$
CREATE PROCEDURE some_proc ()
BEGIN
-- creating a unique value
DECLARE VARIABLE tmp_uuid varchar(50);
SET tmp_uuid = uuid();
CREATE TEMPORARY TABLE IF NOT EXISTS tbl_temporary
(
uuid_id varchar(50),
col1 varchar(10),
col2 varchar(10),
INDEX(uuid_id)
);
-- do some operations on that
INSERT INTO tbl_temporary(uuid_id, ...) VALUES (tmp_uuid,...);
-- now, cleaning the data
DELETE FROM tbl_temporary WHERE uuid_id = tmp_uuid;
-- if the current session is closed the table will be automatically deleted
END$$
DELIMITER ;

How to use DROP TABLE IF EXISTS in a MySQL Stored Procedure

I want to know how to use DROP TABLE IF EXISTS in a MySQLstored procedure.
I'm writing a rather long mySQL Stored Procedure that will do a bunch of work and then load up a temp table with the results. However, I am having trouble making this work.
I've seen a few ways to do the temp table thing. Basically, you either create the temp table, work on it, and then drop it at the end ... or you drop it if it exists, create it, and then do your work on it.
I prefer the second method so that you always start of clean, and it's a built-in check for the table's existence. However, I can't seem to get it to work:
Here are my examples:
This Works:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
DROP TEMPORARY TABLE tblTest;
END//
DELIMITER ;
CALL pTest();
This Works:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
CALL pTest();
This does not:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
CALL pTest();
The first 2 work, but if that table exists (like if the procedure didn't finish or something), it'll obviously end with a "Table tblTest does not exist" error. The non-working example is what I'm looking for -- drop the table if its there and then recreate it so that I can start clean.
It feels like it's the "IF EXISTS" making this thing fail. I've copied code from all sorts of sites that do things very similar and in no case can I get a "DROP TABLE IF EXISTS..." to work. Ever.
Dev Server: mySQL Server version: 5.1.47-community
Prod Server: mySQL Server version: 5.0.45-log
We can't change db versions (DBAs won't allow it), so I'm stuck on what I have. Is this a bug in mySQL or in the Procedure?
Thanks.
It's an old question but it came up as I was looking for DROP TABLE IF EXISTS.
Your non-working code did not work on my MySQL 5.1.70 server.
All I had to do was add a space between DELIMITER and // on the first line, and everything worked fine.
Working code:
DELIMITER //
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
I don't know why this is not working for you,but you should be able to work around the issue using a continue handler. If you put the DROP TABLE statement into it's own BEGIN...END block you can use a continue handler to ignore the error if the table does not exist.
Try this:
DELIMITER //
DROP PROCEDURE IF EXISTS pTest //
CREATE PROCEDURE pTest()
BEGIN
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' BEGIN END;
DROP TEMPORARY TABLE tblTest;
END;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END //
DELIMITER ;
CALL pTest();
I also had the same problem. It seems MySQL doesn't like to check if the table exists on some versions or something. I worked around the issue by querying the database first, and if I found a table I dropped it. Using PHP:
$q = #mysql_query("SELECT * FROM `$name`");
if ($q){
$q = mysql_query("DROP TABLE `$name`");
if(!$q) die('e: Could not drop the table '.mysql_error());
}
You suppress the error in the first query with the # symbol, so you don't have an interfering error, and then drop the table when the query returns false.
I recommend to add new line
SET sql_notes = 0// before DROP PROCEDURE IF EXISTS get_table //
Otherwise it will show warning PROCEDURE does not exists.