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.
Related
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
I am using MySql and I am trying to create a Partition in a table, using a stored procedure.
I have the following table in MySql -
CREATE TABLE `snapshot` (
`user_id` bigint(20) NOT NULL,
`latest_transaction_id` bigint(20) NOT NULL,
`balance` decimal(15,2) NOT NULL DEFAULT '0.00',
`last_transaction_timestamp` bigint(20) NOT NULL,
`last_transaction_date` datetime NOT NULL,
`snapshot_date` date NOT NULL,
`year` smallint(6) NOT NULL
)
/*!50500 PARTITION BY LIST COLUMNS(`year`)
(PARTITION snapshot_2017 VALUES IN (2017),
PARTITION snapshot_2016 VALUES IN (2016),
PARTITION snapshot_2018 VALUES IN (2018)) */
I have written a stored procedure which is -
1. Getting current year name
2. Adding a prefix to the year
3. And then creating a new partition, using the prefix+year name
The idea is the data of a certain year, should belong to that particular year’s partition.
Following is the stored procedure -
CREATE DEFINER=`root`#`localhost` PROCEDURE `process_snapshot`()
BEGIN
DECLARE snapshot_year INT;
DECLARE partition_name VARCHAR(17);
DECLARE isPartionPresent VARCHAR(64);
SET snapshot_year := DATE_FORMAT(NOW(),'%Y');
SET partition_name := CONCAT('snapshot_',snapshot_year);
SET isPartionPresent := (SELECT DISTINCT PARTITION_NAME
FROM
INFORMATION_SCHEMA.PARTITIONS
WHERE
TABLE_NAME = 'snapshot'
AND PARTITION_NAME = partition_name);
IF isPartionPresent IS NULL THEN
SET #addPartition = CONCAT('ALTER TABLE snapshot ADD PARTITION (PARTITION ', partition_name, ' VALUES IN (', snapshot_year,'))');
PREPARE _stmt FROM #addPartition;
EXECUTE _stmt;
DEALLOCATE PREPARE _stmt;
END IF;
END
I am getting the following error when I run the SP -
Error Code: 1526. Table has no partition for value from column_list
However, if I run the following SP separately, I am able to create a partition successfully,
CREATE DEFINER=`root`#`localhost` PROCEDURE `create_table_partition`()
BEGIN
DECLARE snapshot_year INT;
DECLARE partition_name VARCHAR(17);
SET snapshot_year := DATE_FORMAT(NOW(),'%Y');
SET partition_name := CONCAT('snapshot_',snapshot_year);
SET #addPartition = CONCAT('ALTER TABLE snapshot ADD PARTITION (PARTITION ', partition_name, ' VALUES IN (', snapshot_year,'))');
PREPARE _stmt FROM #addPartition;
EXECUTE _stmt;
DEALLOCATE PREPARE _stmt;
END
But if I call this SP, from my main SP, it gives the same error,
What could be the issue?
I want all the tables' list with corresponding count of number of NULL entries in column 'user'. I have printed all table's name beginning with cm using
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES WHERE (TABLE_NAME LIKE 'cm%') ;
but for each table i want to run
SELECT COUNT(1) FROM <TABLENAME> WHERE `create_user` IS NULL
OR `create_time` IS NULL
and print
Create the table below, replacing it with the correct database name:
CREATE TABLE `db`.`tbl_count_null` (
`tableschema` varchar(64) NOT NULL DEFAULT '',
`tablename` varchar(64) NOT NULL DEFAULT '',
`qtd` char(0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
See if the procedure below meets you:
CREATE DEFINER=`user`#`%` PROCEDURE `nameprocedure`()
BEGIN
DECLARE x, y LONGTEXT;
DECLARE done INT DEFAULT 0;
DECLARE databasesCursor CURSOR FOR
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'cm%';
DECLARE CONTINUE HANDLER
FOR SQLSTATE '02000' SET done = 1;
OPEN databasesCursor;
myLoop: LOOP
FETCH databasesCursor INTO x, y;
IF NOT done THEN
SET #query = CONCAT("INSERT INTO`db`.`tbl_count_null` (tableschema, tablename, qtd) SELECT '",x,"' AS `schema`,'",y,"' AS `table`,COUNT(1) FROM `",x,"`.`",y,"` WHERE `create_user` IS NULL OR `create_time` IS NULL;");
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP myLoop;
CLOSE databasesCursor;
END;
After creating the above procedure, call with the command:
call db.nameprocedure;
Verify that the records have been inserted into the table db.tbl_count_null
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 ;
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.