mysql stored procedure dynamic if else block like eval - mysql

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 ?

Related

MySQL MyISAM query still optimized when the first column is null

In MySQL offcial document for count,there are descriptions as below:
For MyISAM tables, COUNT(*) is optimized to return very quickly if the SELECT retrieves from one > table, no other columns are retrieved, and there is no WHERE clause. For example:
mysql> SELECT COUNT(*) FROM student;
This optimization only applies to MyISAM tables, because an exact row count is stored for this >storage engine and can be accessed very quickly. COUNT(1) is only subject to the same >optimization if the first column is defined as NOT NULL.
I want to test it for myself, and make a test as below,I make a table called system_user and the first column is type,all the value of type is null,however when I use SELECT COUNT(1) and SELECT COUNT(*) to query, I found the time cost is nearly the same,even if tried for serval times.
I am wonder why the first column is null and the optimization in MyISAM is still working?
When I use SQL_NO_CACHE,the time cost is still nearly the same:
related table:
CREATE TABLE `system_user` (
`type` varchar(10) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(8) NOT NULL,
`age` int(11) DEFAULT NULL,
`tag` varchar(8) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
related procdure to create massive data:
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `add_user_batch`$$
CREATE DEFINER=`root`#`%` PROCEDURE `add_user_batch`(IN COUNT INT)
BEGIN
DECLARE i INT;
DECLARE t_name VARCHAR(8);
DECLARE t_tag VARCHAR(20);
DECLARE t_age INT(2);
DECLARE t_sql_template VARCHAR(100);
DECLARE t_sql TEXT;
DECLARE t_tag_mod_val INT DEFAULT(25);
DECLARE t_commit_mod_val INT DEFAULT(100);
DECLARE t_start_time DATETIME;
DECLARE t_end_time DATETIME;
TRUNCATE TABLE `system_user`;
SET t_start_time=NOW();
SET t_sql_template = “INSERT INTO `system_user`(NAME, age, tag) VALUES“;
SET t_sql = t_sql_template;
SET i = 1;
WHILE i <= COUNT
DO
SET t_age = FLOOR(1 + RAND() * 60);
SET t_name = LEFT(UUID(), 8);
IF MOD(i, t_tag_mod_val) = 0 THEN
SET t_tag = “NULL“;
ELSE
SET t_tag = CONCAT(“'“,LEFT(UUID(), 8),“'“);
END IF;
SET t_sql = CONCAT(t_sql,“('“,t_name,“',“,t_age,“,“,t_tag,“)“);
IF MOD(i,t_commit_mod_val) != 0 THEN
SET t_sql = CONCAT(t_sql,“,“);
ELSE
SET t_sql = CONCAT(t_sql,“;“);
SET #insert_sql = t_sql;
PREPARE stmt FROM #insert_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
SET t_sql=t_sql_template;
END IF;
SET i = i + 1;
END WHILE;
IF LENGTH(t_sql) > LENGTH(t_sql_template) THEN
SET t_sql=CONCAT(SUBSTRING(t_sql,1,LENGTH(t_sql)-1),';');
SET #insert_sql = t_sql;
PREPARE stmt FROM #insert_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
END IF;
SET t_end_time=NOW();
SELECT CONCAT('insert data success,time cost ',TIMEDIFF(t_end_time,t_start_time)) AS finishedTag;
END$$
DELIMITER ;

the count of row( user) for each table begining with cm in the schema

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

Create a table dynamically in mysql with parameters which I pass as column names

I want to create a table through stored procedure. I can do it by specifying static column names but I want the column names to be dynamic like arguments which I pass through call method will be column names.
My sample code is this :
DELIMITER $$
CREATE PROCEDURE table_creation(IN column1 VARCHAR(20),IN column2 VARCHAR(20),IN column3 VARCHAR(20),IN column4 VARCHAR(20))
BEGIN
CREATE TABLE mytable(column1 VARCHAR(20),column2 VARCHAR(20), column3 VARCHAR(20), column4 VARCHAR(20));
END $$
DELIMITER;
CALL table_creation(name1,location,working,designation);
Please find below answer , i hope this will helpful to you.
BEGIN
#Routine body goes here...
SET SESSION group_concat_max_len = (2056 * 2056);
SET #sql = NULL;
SET #sql = CONCAT('Create table if not EXISTS my_table (column1 VARCHAR(20),column2 VARCHAR(20), column3 VARCHAR(20), column4 VARCHAR(20)) ENGINE=MyISAM DEFAULT CHARSET=utf8 ');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Let me know if you fetch any problem.

MySQL - Alter table syntax in stored procedure

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 ;

Mysql Prepared Statement with Constraint

I have a Table Structure as below
CREATE TABLE `eatables` (
`Sno` int(11) NOT NULL auto_increment,
`Name` varchar(255) collate latin1_general_ci default NULL,
PRIMARY KEY (`Sno`)
);
The Table contains Rows as below
insert into `eatables`(`Sno`,`Name`) values (1,'Apples');
insert into `eatables`(`Sno`,`Name`) values (2,'Oranges');
insert into `eatables`(`Sno`,`Name`) values (3,'Papaya');
insert into `eatables`(`Sno`,`Name`) values (4,'Jackfruit');
insert into `eatables`(`Sno`,`Name`) values (5,'Pineapple');
insert into `eatables`(`Sno`,`Name`) values (6,'Mango');
I created a Procedure to get the Count based on Name as Constraint
DROP PROCEDURE IF EXISTS proc_fruit_count;
CREATE PROCEDURE mp_user_preference(pFruitName VARCHAR(255))
BEGIN
SELECT #lngCount = COUNT(Sno)
FROM eatables
WHERE Name = pFruitName;
SELECT #lngCount;
END
But my Procedure is returning Null every time I execute it.
You have to modify your stored procedure! You also need to use IN keyword:
CREATE PROCEDURE mp_user_preference(IN pFruitName VARCHAR(255))
BEGIN
SELECT #lngCount = COUNT(Sno)
FROM eatables
WHERE Name = pFruitName;
SELECT #lngCount;
END
See http://www.mysqltutorial.org/stored-procedures-parameters.aspx
Edit:If you want to return lngCount you can modify the stored procedure as follow:
CREATE PROCEDURE mp_user_preference(IN pFruitName VARCHAR(255), OUT toReturn INT)
BEGIN
SELECT #lngCount = COUNT(Sno)
FROM eatables
WHERE Name = pFruitName
INTO toReturn;
END
You don't need a stored procedure here. You can solve this conveniently with a prepared statement.
prepare stmt from 'select count(*) from eatables where name = ?';
set #whatever = 'Mango';
execute stmt using #whatever; /* #whatever replaces the ? in the query above */
/* and if you don't need the prepared statement any more you do... */
deallocate prepare stmt;
Read more about prepared statements here.