MySQL - Alter table syntax in stored procedure - mysql

I've created a stored procedure to change the column name as below.
Table structure:
CREATE TABLE ``procedurecheck`` (
``id`` int(10) NOT NULL AUTO_INCREMENT,
``colname`` varchar(50) NOT NULL,
``proccheck1`` varchar(50) NOT NULL,
PRIMARY KEY (``id``)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
This is a test code only to check procedures.
DELIMITER $$
CREATE PROCEDURE updateColumn(IN COLNAME varchar (50), IN NEWCOLNAME varchar (50))
BEGIN
SET #ddl = CONCAT('alter table procedurecheck CHANGE (', COLNAME, ' ', NEWCOLNAME, ' VARCHAR(50) NOT NULL)');
PREPARE STMT FROM #ddl;
EXECUTE STMT;
END $$
DELIMITER ;
When i call this function using:
CALL updateColumn('proccheck','newproccheck');
i get an error as follws:
#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 '(proccheck newproccheck VARCHAR(50) NOT NULL)' at line 1
Any pointers would be helpful.
Thanks

remove (), eg.
CONCAT('alter table procedurecheck CHANGE ', COLNAME, ' ', NEWCOLNAME, ' VARCHAR(50) NOT NULL');

DROP PROCEDURE IF EXISTS pl_updateColumnName;
DELIMITER $$
CREATE PROCEDURE pl_updateColumnName(IN tblName varchar (50), IN COLNAME varchar (50), IN NEWCOLNAME varchar (50))
BEGIN
SET #ddl = CONCAT(' alter table ', tblName ,' CHANGE ', COLNAME, ' ', NEWCOLNAME, ' VARCHAR(50) NOT NULL');
PREPARE STMT FROM #ddl;
EXECUTE STMT;
END $$
DELIMITER ;

You may try this stored proc:
DROP PROCEDURE IF EXISTS pl_alterColumnName;
DELIMITER $$
CREATE PROCEDURE pl_alterColumnName(IN tblName varchar (50), IN COLNAME varchar (50), IN NEWCOLNAME varchar (50))
BEGIN
SET #ddl = CONCAT(' alter table ', tblName ,' CHANGE ', COLNAME, ' ', NEWCOLNAME, ' VARCHAR(50) NOT NULL');
PREPARE STMT FROM #ddl;
EXECUTE STMT;
END $$
DELIMITER ;

Related

How do I create table if a reference record doesn't exist else insert?

I designed a system which received request with ResortId, DayId, SkierId, Time, LiftId.
I created a table called day_resort with ResortId, DayId, and a reference which equals the concatenation of ResortId and DayId. When I received a request with Reference (ResortId + DayId) exists in the day_resort. I will simply find the table with name = Reference and insert SkierId, Time, and LiftId there. On the contrary, if I don't find certain Reference in day_resort, I will create a table name after ResortId + DayId, and I will insert the record with ResortId, DayId, ResortId + DayId into day_resort, after that, I will go to the table name after ResortId + DayId and insert a record with SkierId, Time, and LiftId.
Here is the example I tried:
DELIMITER //
DROP PROCEDURE IF EXISTS createLogTable;
CREATE PROCEDURE createLogTable(tblName VARCHAR(255))
BEGIN
SET #tableName = tblName;
SET #sql := CASE
WHEN NOT EXISTS (SELECT * FROM day_resort WHERE Reference = #tableName) THEN
'INSERT INTO day_resort (ResortId, DayId, Reference) VALUES ("Marriot", "21", "Marriot21")';
ELSE
CONCAT('INSERT INTO `' , #tableName, '` (SkierId, TIme, LiftId) VALUES ("111", "222", "333")');
END;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
CREATE TABLE IF NOT EXISTS #tableName (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
SkierId VARCHAR(255) NOT NULL
Time VARCHAR(255) NOT NULL,
LiftId VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
END //
I got an error of Error Code: 2014 Commands out of sync; you can't run this command now
Thanks for any help

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.

Change auto increment starting number?

In MySQL, I have a table, and I want to set the auto_increment value to 5 instead of 1. Is this possible and what query statement does this?
You can use ALTER TABLE to change the auto_increment initial value:
ALTER TABLE tbl AUTO_INCREMENT = 5;
See the MySQL reference for more details.
Yes, you can use the ALTER TABLE t AUTO_INCREMENT = 42 statement. However, you need to be aware that this will cause the rebuilding of your entire table, at least with InnoDB and certain MySQL versions. If you have an already existing dataset with millions of rows, it could take a very long time to complete.
In my experience, it's better to do the following:
BEGIN WORK;
-- You may also need to add other mandatory columns and values
INSERT INTO t (id) VALUES (42);
ROLLBACK;
In this way, even if you're rolling back the transaction, MySQL will keep the auto-increment value, and the change will be applied instantly.
You can verify this by issuing a SHOW CREATE TABLE t statement. You should see:
> SHOW CREATE TABLE t \G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
...
) ENGINE=InnoDB AUTO_INCREMENT=43 ...
How to auto increment by one, starting at 10 in MySQL:
create table foobar(
id INT PRIMARY KEY AUTO_INCREMENT,
moobar VARCHAR(500)
);
ALTER TABLE foobar AUTO_INCREMENT=10;
INSERT INTO foobar(moobar) values ("abc");
INSERT INTO foobar(moobar) values ("def");
INSERT INTO foobar(moobar) values ("xyz");
select * from foobar;
'10', 'abc'
'11', 'def'
'12', 'xyz'
This auto increments the id column by one starting at 10.
Auto increment in MySQL by 5, starting at 10:
drop table foobar
create table foobar(
id INT PRIMARY KEY AUTO_INCREMENT,
moobar VARCHAR(500)
);
SET ##auto_increment_increment=5;
ALTER TABLE foobar AUTO_INCREMENT=10;
INSERT INTO foobar(moobar) values ("abc");
INSERT INTO foobar(moobar) values ("def");
INSERT INTO foobar(moobar) values ("xyz");
select * from foobar;
'11', 'abc'
'16', 'def'
'21', 'xyz'
This auto increments the id column by 5 each time, starting at 10.
You can also do it using phpmyadmin. Just select the table than go to actions. And change the Auto increment below table options. Don't forget to click on start
Procedure to auto fix AUTO_INCREMENT value of table
DROP PROCEDURE IF EXISTS update_auto_increment;
DELIMITER //
CREATE PROCEDURE update_auto_increment (_table VARCHAR(64))
BEGIN
DECLARE _max_stmt VARCHAR(1024);
DECLARE _stmt VARCHAR(1024);
SET #inc := 0;
SET #MAX_SQL := CONCAT('SELECT IFNULL(MAX(`id`), 0) + 1 INTO #inc FROM ', _table);
PREPARE _max_stmt FROM #MAX_SQL;
EXECUTE _max_stmt;
DEALLOCATE PREPARE _max_stmt;
SET #SQL := CONCAT('ALTER TABLE ', _table, ' AUTO_INCREMENT = ', #inc);
PREPARE _stmt FROM #SQL;
EXECUTE _stmt;
DEALLOCATE PREPARE _stmt;
END//
DELIMITER ;
CALL update_auto_increment('your_table_name')
If you need this procedure for variable fieldnames instead of id this might be helpful:
DROP PROCEDURE IF EXISTS update_auto_increment;
DELIMITER //
CREATE PROCEDURE update_auto_increment (_table VARCHAR(128), _fieldname VARCHAR(128))
BEGIN
DECLARE _max_stmt VARCHAR(1024);
DECLARE _stmt VARCHAR(1024);
SET #inc := 0;
SET #MAX_SQL := CONCAT('SELECT IFNULL(MAX(',_fieldname,'), 0) + 1 INTO #inc FROM ', _table);
PREPARE _max_stmt FROM #MAX_SQL;
EXECUTE _max_stmt;
DEALLOCATE PREPARE _max_stmt;
SET #SQL := CONCAT('ALTER TABLE ', _table, ' AUTO_INCREMENT = ', #inc);
PREPARE _stmt FROM #SQL;
EXECUTE _stmt;
DEALLOCATE PREPARE _stmt;
END //
DELIMITER ;
CALL update_auto_increment('your_table_name', 'autoincrement_fieldname');
just export the table with data ..
then copy its sql like
CREATE TABLE IF NOT EXISTS `employees` (
`emp_badgenumber` int(20) NOT NULL AUTO_INCREMENT,
`emp_fullname` varchar(100) NOT NULL,
`emp_father_name` varchar(30) NOT NULL,
`emp_mobile` varchar(20) DEFAULT NULL,
`emp_cnic` varchar(20) DEFAULT NULL,
`emp_gender` varchar(10) NOT NULL,
`emp_is_deleted` tinyint(4) DEFAULT '0',
`emp_registration_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`emp_overtime_allowed` tinyint(4) DEFAULT '1',
PRIMARY KEY (`emp_badgenumber`),
UNIQUE KEY `bagdenumber` (`emp_badgenumber`),
KEY `emp_badgenumber` (`emp_badgenumber`),
KEY `emp_badgenumber_2` (`emp_badgenumber`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=111121326 ;
now change auto increment value and execute sql.