How to create an Archive Table with a Mysql Procedure and Date() - mysql

I try to create a procedure which runs once a day and stores a subset of data from a bigger Table. The Name of this table should be dynamically created with CURDATE().
DROP PROCEDURE daily_backup;
DELIMITER |
CREATE PROCEDURE daily_backup()
BEGIN
SET #tbl = CONCAT('items_data_', DATE_FORMAT(CURDATE(), '%Y%m%d'));
SET #s = CONCAT('DROP TABLE IF EXISTS ', #tbl);
PREPARE stmt FROM #s;
EXECUTE stmt;
#s = CONCAT('CREATE TABLE `', #tb1, '` (`id` int(11) NOT NULL,`up` mediumint(9) NOT NULL,`down` mediumint(9) NOT NULL) ENGINE=Archive');
PREPARE stmt FROM #s;
EXECUTE stmt;
SET #s = CONCAT('INSERT INTO ', #tbl, ' SELECT id,up,down FROM items;');
PREPARE stmt FROM #s;
EXECUTE stmt;
END
These are the results
#1064 - 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 '#s = CONCAT('CREATE TABLE `', #tb1, '` (`id` int(11) NOT NULL,`up` mediumint(9) ' at line 8
EDIT // Working now
DROP PROCEDURE daily_backup;
DELIMITER |
CREATE PROCEDURE daily_backup()
BEGIN
SET #tbl = CONCAT('items_data_', DATE_FORMAT(CURDATE(), '%Y%m%d'));
SET #s = CONCAT('DROP TABLE IF EXISTS ', #tbl);
PREPARE stmt FROM #s;
EXECUTE stmt;
SET #s = CONCAT('CREATE TABLE `', #tbl, '` (`id` int(11) NOT NULL,`up` mediumint(9) NOT NULL,`down` mediumint(9) NOT NULL) ENGINE=Archive');
PREPARE stmt FROM #s;
EXECUTE stmt;
SET #s = CONCAT('INSERT INTO ', #tbl, ' SELECT id,up,down FROM items;');
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END

Variable assignments always need a SET command:
SET #s = CONCAT('CREATE TABLE `', #tbl, '` (`id` int(11) NOT NULL,`up` mediumint(9) NOT NULL,`down` mediumint(9) NOT NULL) ENGINE=Archive');
Note that you have #tb1 in this statement, it should be #tbl.
It's also good practice to DEALLOCATE a prepared statement after you use it i.e.
DEALLOCATE PREPARE stmt;
after the EXECUTE stmt

Related

Create table and insert using variable

I'd like to create a table and insert data only changing the variable name.
but instead, it creates a table with the name #myId, and not with the value of the variable.
i also have tried to remove the `` but i got an sql error.
set #myId = "tabletest";
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
CREATE TABLE `#myId` (
`id` int(10) NOT NULL,
`position` int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `#myId` (`id`, `position`) VALUES
(1, 1);
I am not recommending that you do this. Table names should not be coming from variables. However, you did ask a valid question and if you were going to do this, you need dynamic SQL:
SET #sql = 'CREATE TABLE #myId (id int(10) NOT NULL, position int(10) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;';
SET #sql = REPLACE(#sql, '#myId', 'tabletest');
PREPARE ct FROM #sql;
EXECUTE ct;
DEALLOCATE PREPARE ct;
SET #sql = 'INSERT INTO #myId (id, position) VALUES (1, 1);';
SET #sql = REPLACE(#sql, '#myId', 'tabletest');
PREPARE st FROM #sql;
EXECUTE st;
DEALLOCATE PREPARE st;
You can then execute:
SELECT * FROM tabletest;
Note that if you wanted to use #myId in the SELECT, you would need more dynamic SQL: Yucch!
Usually the right solution is just a table where you insert rows with an identifier. You can then delete those rows (or invalidate them) if necessary when you are done.
Here is a db<>fiddle.

Mysql 5.7 Stored Procedure error

I an trying to create stored procedure in following format :
DELIMITER $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'`(
`id` bigint(20) NOT NULL DEFAULT '0',
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`lattitude` float NOT NULL DEFAULT '0',
`longitude` float NOT NULL DEFAULT '0',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END
$$
DELIMITER ;
-- When I am trying to execute this query in Mysql 5.7 I am getting following error
ERROR 1064 (42000): 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 '');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE SET #sql = CONCAT' at line 10
Can anyone help to improve this sotred procedure ?
This should work. Pay attention to order of single quotes as it can get tricky.
DELIMITER $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN
SET #sql = CONCAT('INSERT INTO ',tableName,' (timestamp, lattitude, longitude,systime) VALUES (',ts, ',', lat, ',', lon, ',', systs, ')' );
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'` (
`id` bigint(20) NOT NULL DEFAULT 0,
`timestamp` bigint(20) NOT NULL DEFAULT 0,
`lattitude` float NOT NULL DEFAULT 0,
`longitude` float NOT NULL DEFAULT 0,
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id) )' );
PREPARE stmt FROM #sql;
EXECUTE stmt;
END IF;
SET #sql = CONCAT('INSERT INTO ',tableName,' (timestamp, lattitude, longitude,systime) VALUES (',ts, ',', lat , ',', lon, ',', systs, ')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
END
$$
DELIMITER ;
You are using single quote (') for the concat string of your create table statement and the default values within it.
Either put the default values in double quotes ("), escape them (\') or remove them as they are all numberic types.
Edit: Your parameters for the insert statements are also put into quotes which looks wrong, too.
create schema mine;
use mine;
delimiter $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs\')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE ',tableName,'(
`id` bigint(20) NOT NULL DEFAULT \'0\',
`timestamp` bigint(20) NOT NULL DEFAULT \'0\',
`lattitude` float NOT NULL DEFAULT \'0\',
`longitude` float NOT NULL DEFAULT \'0\',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs\')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END if;
end
$$
DELIMITER ;
You can try above code;
Firstly you need to escape all Single quote '
And you forgot to close ENDIF.
In the marked comment, this code was missing a quote to complete concat correctly
$$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs',')'); /* Error in this line */
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'`(
`id` bigint(20) NOT NULL DEFAULT '0',
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`lattitude` float NOT NULL DEFAULT '0',
`longitude` float NOT NULL DEFAULT '0',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END
$$
DELIMITER ;

mysql stored procedure dynamic if else block like eval

This is a simple working example
DROP PROCEDURE IF EXISTS `test`;
CREATE PROCEDURE `test`(
IN invar VARCHAR(255),
OUT outvar VARCHAR(255)
)
BEGIN
IF(invar = 1) THEN
SET outvar = 'ok';
END IF;
END;
But is it possible to do something like this to work in mysql?
DROP PROCEDURE IF EXISTS `test`;
CREATE PROCEDURE `test`(
IN invar VARCHAR(255),
OUT outvar VARCHAR(255)
)
BEGIN
SET #vs_query = CONCAT(
"IF(invar = 1)",
"SET outvar = 'ok';",
"END IF;"
);
PREPARE stmt FROM #vs_query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
Something like EVAL #vs_query string in mysql ?

Mysql dynamic trigger creation in stored procedure

I want to create the dynamic trigger when call the procedure, it give the mysql server version syntax error, when i select that query and execute in separate query editor it will be executed.
DROP TABLE IF EXISTS auditLog;
CREATE TABLE `auditlog` (
`tableName` VARCHAR(255) DEFAULT NULL,
`rowPK` INT(11) DEFAULT NULL,
`fieldName` VARCHAR(255) DEFAULT NULL,
`old_value` VARCHAR(255) DEFAULT NULL,
`new_value` VARCHAR(255) DEFAULT NULL,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=ARCHIVE;
CREATE TABLE country(countryname VARCHAR(100);
DROP PROCEDURE IF EXISTS addLogTrigger;
DELIMITER $
/*
call addLogTrigger('country','CountryID','CountryName')
*/
CREATE PROCEDURE addLogTrigger
(IN tableName VARCHAR(255), IN pkField VARCHAR(255),IN column_name VARCHAR(50))
BEGIN
SET #qry = CONCAT
(
'
DROP TRIGGER IF EXISTS ', tableName, '_AU ;
CREATE TRIGGER ', tableName, '_AU AFTER UPDATE ON ', tableName, '
FOR EACH ROW
','
INSERT INTO auditLog (',
'tableName, ',
'rowPK, ',
'fieldName, ',
'old_value, ',
'new_value'
') VALUES
( ''',
tablename, ''', NEW.',
pkField, ', ''',
column_name, ''', OLD.',
column_name, ', NEW.',
column_name,
');
'
, '
'
) ;
SELECT #qry;
PREPARE stmt FROM #qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$
DELIMITER ;
Karthikeyan,
You can not create a trigger inside stored procedure.
Trigger is a DDL statement which is not allowed inside procedures.
" ERROR 1303 (2F003): Can't create a TRIGGER from within another stored routine "
To solve your purpose you can do following:
Take current values from table inside variable.
Simply write a update query inside your procedure, then check whether value is updated or not by "ROW_COUNT()".
Compare new value with old value, of changed then manually insert into change_log table.

How to insert data from an EXECUTE statement in mySql?

I have data in a wp_users table, and I want to duplicate the data from that table (except for the ID column) into another table, called wp_users2.
If I didn't care about the id column, which I want to auto-increment, I could just do this:
insert into wp_users2 (select *, NULL as ID from wp_users)
So I know I could do this by typing out all of the column headers except for ID and manually selecting that one as NULL,
SELECT NULL as id, col2, col3...
but I'd like to do it dynamically. I read this great S.O. post about how to do that, and it works, however I can't figure out how to take the data it gives me and put it into an insert statement.
INSERT INTO wp_users2 (
SET #sql = CONCAT('SELECT NULL as ID,',
(SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'ID,', '')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'wp_users'
AND TABLE_SCHEMA = 'wp1'),
' FROM wp_users');
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
)
What's the right syntax for that?
As I understand - id is AUTO_INCREMENT field.
So, try to use this script as an example for your task -
CREATE TABLE table1(
id INT(11) NOT NULL AUTO_INCREMENT,
column1 VARCHAR(255) DEFAULT NULL,
column2 VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE TABLE table2(
id INT(11) NOT NULL AUTO_INCREMENT,
column1 VARCHAR(255) DEFAULT NULL,
column2 VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
);
INSERT INTO table1 VALUES
(1, 'c1', 'c2'),
(2, 'c3', 'c4');
SET #source_table = 'table1';
SET #target_table = 'table2';
SET #id = 'id';
SET #columns = NULL;
SELECT group_concat(column_name) INTO #columns FROM information_schema.columns
WHERE
table_schema = 'database_name' -- Set your database name here
AND table_name = #source_table
AND column_name != #id;
SET #insert = concat('INSERT INTO ', #target_table, '(', #id, ',', #columns, ') SELECT NULL, ', #columns, ' FROM ', #source_table);
PREPARE stmt1 FROM #insert;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
set #sql = (select concat('insert into wp_users2 SELECT NULL,',
group_concat(column_name),' from ',table_name) from information_schema.columns
where table_name = 'wp_users' and table_schema = 'wp1' and column_name != 'id'
order by ordinal_position);
prepare stmt1 from #sql;
execute stmt1;
deallocate prepare stmt1;