Delete all users in MySQL with specific name - mysql

I want to delete all users from my MySQL database with specified name regardless to the host parameter. Here is what I wrote:
DELIMITER ;;
## CREATING SCHEMA
DROP SCHEMA IF EXISTS rms;;
CREATE SCHEMA rms;;
USE rms;;
## DROP USER
DROP PROCEDURE IF EXISTS PREPARE_USERS;;
CREATE PROCEDURE PREPARE_USERS()
BEGIN
DECLARE V_RECORD_NOT_FOUND INTEGER DEFAULT 0;
DECLARE V_USER_HOST CHAR(60);
DECLARE C_HOSTS_CURSOR CURSOR FOR
SELECT host FROM mysql.user WHERE user='rms';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET V_RECORD_NOT_FOUND = 0;
OPEN C_HOSTS_CURSOR;
READ_LOOP: LOOP
FETCH C_HOSTS_CURSOR INTO V_USER_HOST;
IF V_RECORD_NOT_FOUND != 0 THEN
LEAVE READ_LOOP;
END IF;
SET #V_EXEC=CONCAT(CONCAT('DROP USER \'rms\'#\'',V_USER_HOST),'\';;');
PREPARE V_STMT FROM #V_EXEC;
EXECUTE V_STMT;
DEALLOCATE PREPARE V_STMT;
END LOOP;
CLOSE C_HOSTS_CURSOR;
FLUSH PRIVILEGES;
CREATE USER 'rms'#'127.0.0.1' IDENTIFIED BY 'rms123';
GRANT ALL ON rms.* TO 'rms'#'127.0.0.1'
WITH MAX_USER_CONNECTIONS 250;
END;;
CALL PREPARE_USERS();;
DROP PROCEDURE IF EXISTS PREPARE_USERS;;
DELIMITER ;
But it gives me errors and I don't know why :/ When there are no users with 'rms' name, it won't even run, but if there are any, MySQL claims that they can't be dropped even though they are.

OK, I have the answer:
SET #users = NULL;
SELECT GROUP_CONCAT('\'',user, '\'#\'', host, '\'') INTO #users FROM mysql.user WHERE user = 'rms';
SET #users = CONCAT('DROP USER ', #users);
PREPARE stmt1 FROM #users;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

Related

Create stored procedure with specific schema in MYSQL and grant execute permission to user

Hello i have two db schemas "results" and "base". I am trying to create stored procedure in "results" database, and at the same time to give permission to user to run this procedure. What i did is:
DELIMITER //
DROP PROCEDURE IF EXISTS results.truncateResultsTable //
CREATE PROCEDURE results.truncateResultsTable(genId VARCHAR(255))
BEGIN
SET #genId = genId;
SET #q = CONCAT('TRUNCATE TABLE results_' , #genId);
PREPARE stmt FROM #q;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
GRANT EXECUTE ON FUNCTION results.truncateResultsTable TO 'lam_api'#'%';
END //
But getting this error
execute command denied to user 'lam_api'#'%' for routine 'results.truncateResultsTable
Any idea what i am doing wrong?
Here is right solution, i had couple of issues. GARANT part was misplaced, also was missing DELIMITER ;
DELIMITER //
DROP PROCEDURE IF EXISTS results.truncateResultsTable //
CREATE PROCEDURE results.truncateResultsTable(genId VARCHAR(255))
BEGIN
SET #genId = genId;
SET #q = CONCAT('TRUNCATE TABLE results_' , #genId);
PREPARE stmt FROM #q;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
GRANT EXECUTE ON PROCEDURE results.truncateResultsTable TO 'lam_api'#'%';

Creating a Procedure prior to the creation of database and table

I am trying to create a Procedure during the creation of a database, the mysql query is as follows:
CREATE DATABASE database_Sensor1;
USE database_Sensor1;
CREATE TABLE Persons(id int NOT NULL);
DELIMITER //
CREATE PROCEDURE MYLOOP() IF database_Sensor1 EXISTS
BEGIN
DECLARE i int;
DECLARE str varchar(255);
SET i = 0;
WHILE i < 32 DO
SET str = CONCAT('col_',i);
SET #sql = CONCAT('ALTER TABLE persons ADD ',str,' float;');
SET i = i + 1;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END
DELIMITER ;
CALL MYLOOP();
But I get this error:
#1305 - PROCEDURE database_sensor1.MYLOOP does not exist
I am trying to use the Procedure to Loop the table creation by quickly altering the table to add 32 columns in so that I can run another .php to add in the values.
CREATE DATABASE database_Sensor1;
USE database_Sensor1;
CREATE TABLE database_Sensor1.Persons(id int NOT NULL);
DELIMITER //
CREATE PROCEDURE database_Sensor1.MYLOOP()
BEGIN
DECLARE i int;
DECLARE str varchar(255);
SET i = 0;
WHILE i < 32 DO
SET str = CONCAT('col_',i);
SET #sql = CONCAT('ALTER TABLE database_Sensor1.persons ADD ',str,' float;');
SET i = i + 1;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END
//
DELIMITER ;
CALL MYLOOP();
Editions:
IF database_name EXISTS construction not exists. Removed. See edition 3.
Procedure creation code is not finalized with delimiter. Added.
The database in which the procedure must be created is not specified explicitly. Added. If the database not exists then the error will be generated. The same with the table name.

Drop a database if there is no table in it

Is there a MySQL command can do something like:
If there is nothing in a database, drop it. If there is any tables in it, do nothing.
Such as:
drop database if exists foobar
But:
drop database if empty foobar
Is there any way to do this?
As Barmar said you can use INFORMATION_SCHEMA.TABLES with stored procedure.
Here is my small effort:
DELIMITER //
CREATE PROCEDURE spDropDB_IF_Empty()
BEGIN
IF (SELECT COUNT(table_name) from INFORMATION_SCHEMA.tables
WHERE Table_Schema = 'mariadb')= 0 THEN
DROP DATABASE mariadb;
ELSE
SELECT 'There are tables in the mariaDB';
END IF;
END //
DELIMITER ;
Call SP:
CALL spDropDB_IF_Empty()
Hopefully this will help others as well. I just created a procedure for my own purpose after reading your question and commentators' comments.
use mysql;
-- switch to a different delimiter
delimiter $$
create procedure drop_empty_databases()
begin
declare table_schema varchar(200); -- will hold schema obtained from query
declare schema_end int default 0; -- temp variable that's set to 1 when reading of all schema is done
-- cursor that lists all schemas with no tables
declare cur cursor for
select s.schema_name
from information_schema.schemata s
left join information_schema.tables t on t.table_schema = s.schema_name
group by s.schema_name
having count(t.table_name) = 0;
-- set schema_end to 1 when we run out of schemas while looping
declare continue handler for not found set schema_end = 1;
open cur;
looper: loop
fetch cur into table_schema;
if schema_end = 1 then
leave looper;
end if;
set #sql = concat('drop database ', table_schema);
prepare stmt from #sql;
execute stmt;
end loop;
close cur;
end
$$
-- switch back to semi-colon delimiter
delimiter ;
Usage:
use mysql;
create database test123;
call drop_empty_databases(); -- test123 database should be gone after running this
Please test this on a non-production server and confirm that it does what you want it to do.

how can store executed statement (not fetched from a table) in a variable or table

Dear Friends I want to store executed statement's value into a variable or table but right now I am stuck and not able to get the solution, hoping I will get solution here.
my stored procedure:
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `sp_grants`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_grants`(_user VARCHAR(50))
BEGIN
DECLARE done INT(1) DEFAULT 0;
DECLARE _grant TEXT DEFAULT '';
DECLARE cur1 CURSOR FOR SELECT CONCAT('\'', USER ,'\'#\'', HOST,'\'') FROM mysql.user WHERE USER=_user;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- open cursor1
OPEN cur1;
BEGIN
REPEAT
FETCH cur1 INTO _grant;
IF _grant='' THEN
SET done = 1;
END IF;
IF (done<>1) THEN
SET #str1=CONCAT('show grants for ',_grant);
PREPARE stmt1 FROM #str1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END IF;
UNTIL done
END REPEAT;
END;
CLOSE cur1;
-- close cursor1
SELECT 'done';
END$$
DELIMITER ;
Getting below results
CALL sp_grants('zafar');
GRANT USAGE ON *.* TO 'zafar'#'%' IDENTIFIED BY PASSWORD '*20F283F208C26099783173695D6F7BBF24E2346B';
GRANT ALL PRIVILEGES ON `test`.* TO 'zafar'#'%'
I want to store above 2 rows in a variable or table.
Please help me, i will be very thankful.
Note: I know if i was preparing statements from any table data then i can store these statements col1 into #var1 but how can I do here.

passing table name in stored procedure

I am trying to figure out how I can pass part of a table name into a stored procedure and get it to work.
query is
DELIMITER $$
DROP PROCEDURE IF EXISTS vorpaldev.searchLogId2$$
CREATE DEFINER = 'root'#'%'
PROCEDURE vorpaldev.searchLogId2 (userId varchar(300))
BEGIN
SET userId = CONCAT("log", userId);
SET #statment = "Select * from #userId ";
PREPARE stmt FROM #statment;
SET #a = userId;
EXECUTE stmt USING #a;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER
;
I am using
CALL searchLogId2 (131)
to call the code
I want the end results to execute as
Select * from log131
Well! are you going to create seperate table for each user????????? If yes, that is really bad.
I don't know but may be this is your answer. Why dont you pass complete userId in parameter argument 'log131' as
BEGIN
SET #statment = concat('Select * from ',userId);
PREPARE stmt FROM #statment;
EXECUTE stmt USING userId;
DEALLOCATE PREPARE stmt;
END
this will remove overhead of concat