(Related to, but separate from Syntax error with emulating "create user if not exists".)
Is it possible to achieve the functionality of generically/dynamically adding a user (i.e. emulating the sp_adduser system procedure included with other DBMSs) in MySQL?
MySQL doesn't support the following if [not] exists syntax, see http://bugs.mysql.com/bug.php?id=15287:
create user if not exists 'foo'#'%' identified by password 'bar';
It also doesn't support this:
drop procedure if exists create_user_if_not_exists;
delimiter ||
create procedure create_user_if_not_exists
( sUser varchar(60),
sHost varchar(16),
sPassword varchar(255) )
begin
-- ensure user does not yet exist
if (select ifnull((select 1
from mysql.user
where User = sUser
and Host = sHost), 0) = 0) then
set #createUserText = concat('create user ''', sUser, '''#''', sHost, ''' identified by ''', sPassword, ''';');
prepare createUserStatement FROM #createUserText;
execute createUserStatement;
deallocate prepare createUserStatement;
end if;
end ||
delimiter ;
because if you try to call said procedure:
call create_user_if_not_exists ( 'foo', '%', 'bar' );
you get the lovely message:
This command is not supported in the prepared statement protocol yet
The following works, but obviously is not particularly reusable:
drop procedure if exists create_user_if_not_exists;
delimiter ||
create procedure create_user_if_not_exists
( )
begin
if (select ifnull((select 1
from mysql.user
where User = 'foo'
and Host = '%'), 0) = 0) then
create user 'foo'#'%' identified by password 'bar';
end if;
end ||
delimiter ;
Oh sorry i've just twigged you are talking about db users. not application users.
You might like the INSERT INTO ...... ON DUPLICATE KEY UPDATE ......=VALUE(.....) statement.
I use that in my general saving object method, using this i don't have to care if the user exists or not it'll be in there (and up-to-date) after i commit.
Related
I want to create a new user with the same initial password every time I insert a row with the username in the table.
I tried but it doesn't work:
CREATE TABLE IF NOT EXISTS Professeur (
professeur_id int NOT NULL AUTO_INCREMENT,
prenom varchar(40) COLLATE utf8_bin NOT NULL,
name varchar(30) COLLATE utf8_bin NOT NULL,
titre char DEFAULT NULL,
PRIMARY KEY (professeur_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE trigger trig_prof AFTER INSERT ON Professeur
FOR EACH ROW CREATE OR replace USER NEW.name#localhost identified BY pwd0;
ERROR:
ER_PARSE_ERROR: 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
'USER NEW.name#localhost identified BY pwd0' at line 2
Triggers have several limitations as described in the fine manual:
"Triggers cannot operate on any tables in the mysql, information_schema or performance_schema database."
Since users are stored in mysql schema (either in global_priv or user) this can't work.
Do things a different way...
Write a Stored Procedure that both creates the table and adds the user. See SQL SECURITY DEFINER for how to temporarily give an enduser root permission. But be aware of the security implications.
Then, to add the table and the user, it is one CALL statement.
Problem solved with a procedure as Rick James has suggested and with Prepared Statements https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html
I put the following code in my script and I execute the source command SOURCE initdb_gestiondesnotes.SQL
After that I call the procedure with: CALL create_professeur();
DELIMITER $$
CREATE PROCEDURE CREATE_PROFESSEUR()
BEGIN
DECLARE v_a INT Default 1 ;
DECLARE v_nom VARCHAR(42);
DECLARE v_prenom VARCHAR(42);
DECLARE v_login VARCHAR(84);
DECLARE v_titre VARCHAR(5);
DECLARE v_pwd VARCHAR(5);
SET v_pwd = 'p';
simple_loop: LOOP
SET v_nom = CONCAT("prof", LPAD(CAST(v_a AS CHAR), 3, '0'));
SET v_prenom = CONCAT("prenom", LPAD(CAST(v_a AS CHAR), 3, '0'));
SET v_titre = CASE WHEN RAND() > .5
THEN 'M'
ELSE 'F' END;
INSERT INTO Professeur (prenom, nom, titre) VALUES (v_prenom, v_nom, v_titre);
SET v_login = CONCAT(v_prenom, v_nom);
SET #sql1 = CONCAT('CREATE OR REPLACE USER ', v_login, '#localhost identified BY \'p\' ');
PREPARE stm1 FROM #sql1;
EXECUTE stm1;
SET #sql2 = CONCAT('GRANT role_professeur TO ', v_login, '#localhost');
PREPARE stm2 FROM #sql2;
EXECUTE stm2;
SET #sql3 = CONCAT('SET DEFAULT ROLE role_professeur FOR ', v_login, '#localhost');
PREPARE stm3 FROM #sql3;
EXECUTE stm3;
SET v_a=v_a+1;
IF v_a=51 THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
DEALLOCATE PREPARE stm1;
DEALLOCATE PREPARE stm2;
DEALLOCATE PREPARE stm3;
END $$
DELIMITER ;
Now I hove 50 user with prenom001prof001, prenom002prof002... as login and 'p' as password. Again with prepared statements I gave each user the role of role_professeur.
I want to change an user's password using an stored procedure in MySQL.
Here is the creation code:
CREATE SCHEMA `try` ;
USE try;
CREATE TABLE `users` (
`username` VARCHAR(100) NOT NULL,
`password` VARCHAR(100) NOT NULL,
PRIMARY KEY(`username`));
insert into users values('Admin','pass');
create user 'usertry'#'localhost' identified by 'pass';
grant select on try.* to 'usertry'#'localhost';
grant insert on try.* to 'usertry'#'localhost';
grant update on try.* to 'usertry'#'localhost';
grant delete on try.* to 'usertry'#'localhost';
Until here, everything is good.
Then i created a stored procedure to change the table "users".
DELIMITER $$
CREATE PROCEDURE `changeusers` (
IN user VARCHAR(255),
IN pass VARCHAR(255),
IN newuser VARCHAR(255),
IN newpass VARCHAR(255),
OUT result bool)
BEGIN
if(user= Binary (Select username from users limit 1)
and pass= Binary (Select password from users limit 1))
then
delete from users where username=user;
insert into users values(newuser,newpass);
set result=true;
else
set result=false;
end if;
select result;
END $$ DELIMITER ;
When i call the stored procedure, it works well.
call changeusers('Admin','pass','Admin','new',#result);
call changeusers('Admin','pass','Admin','new',#result) 1 row(s) returned 0.141 sec / 0.000 sec
Then i tried to change the stored procedure to set the user's password same as the password in the users table.
DELIMITER $$
CREATE PROCEDURE `changeusers` (
IN user VARCHAR(255),
IN pass VARCHAR(255),
IN newuser VARCHAR(255),
IN newpass VARCHAR(255),
OUT result bool)
BEGIN
if(user= Binary (Select username from users limit 1)
and pass= Binary (Select password from users limit 1))
then
delete from users where username=user;
insert into users values(newuser,newpass);
/*The added line*/
set password for 'usertry'#'localhost' = newpass;
/*The added line*/
set result=true;
else
set result=false;
end if;
select result;
END $$ DELIMITER ;
But when i run the new script i got this:
Error Code: 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
'newpass;
set result=true;
else
set result=false;'
at line 13 0.000 sec
I would apreciate any sugestions.
Thanks.
EDIT
Thanks to #Barmar. I was able to do what i want.
Here's the new stored procedure.
DELIMITER $$
CREATE PROCEDURE `changeusers` (
IN user VARCHAR(255),
IN pass VARCHAR(255),
IN newuser VARCHAR(255),
IN newpass VARCHAR(255),
OUT result bool)
BEGIN
if(user= Binary (Select username from users limit 1)
and pass= Binary (Select password from users limit 1))
then
delete from users where username=user;
insert into users values(newuser,newpass);
/*The added line*/
set #stm = CONCAT("set password for 'usertry'#'localhost' = ",newpass);
prepare stmt from #stm;
execute stmt;
deallocate prepare stmt;
/*The added line*/
set result=true;
else
set result=false;
end if;
select result;
END $$ DELIMITER ;
Thank you so much for your help.
I don't think SET PASSWORD allows the password to be a variable, it has to be a literal (or a call to PASSWORD() with a literal parameter. So you need to use a prepared statement:
PREPARE #stmt FROM CONCAT("SET PASSWORD FOR 'usertry'#'localhost' = '", newpass, "'");
EXECUTE #stmt;
The below is my Stored Procedure(Routine) to check whether or not a user with Username(input) exists in the database.
Inside the database, I already have a user with Username - 'dev'.
However, when I ran the below routine, it returned me with res = 1, which I expected it to be -1.
I called the routine this way. Please correct me too if I am calling it the wrong way. I am really new to MySQL Routines.
CALL usp_GetUserValidation ('dev', #ErrorCode)
Can any MySQL Routine pros here enlighten me on this? Thank you in advance guys :)
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN `#Username` VARCHAR(255), OUT `#ErrorCode` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = #Username)
THEN
SET #ErrorCode = -1;
ELSE
SET #ErrorCode = 1;
END IF;
SELECT #ErrorCode AS res;
END$$
DELIMITER ;
It was simply your naming conventions for the parameters. It is finicky and does not like User Variable # signs in them.
You are just testing I can see, as you are returning both a resultset with the info and the OUT variable.
drop procedure if exists usp_GetUserValidation;
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN pUsername VARCHAR(255), OUT pErrorCode INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = pUsername)
THEN
SET pErrorCode = -1;
ELSE
SET pErrorCode = 1;
END IF;
SELECT pErrorCode AS res;
END$$
DELIMITER ;
Schema:
-- drop table if exists mt_user;
create table mt_User
( UserID int auto_increment primary key,
UserName varchar(100) not null,
unique key(UserName)
);
insert mt_User(UserName) values ('dev');
select * from mt_User;
Test:
set #var1:=-4;
call usp_GetUserValidation('dev',#var1);
-- returns (-1) ---- Yea, we like that
select #var1;
-- (-1)
set #var1:=-4;
call usp_GetUserValidation('dev222',#var1);
-- returns 1 ---- Yea, we like that
select #var1;
-- 1
The Stored Procedure
DELIMITER $$
CREATE PROCEDURE `lms`.`leads_to_bak` ()
BEGIN
SET #table1 = (SELECT `tabler_name` FROM `sets` WHERE `on_off`=0 LIMIT 1);
SET #table2 = CONCAT(#table1, '_bak');
SET #SQL1 = CONCAT('INSERT INTO ',#table2, '(', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'lead_id,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #table2), ')', ' SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'lead_id,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #table1), ' FROM ', #table1);
PREPARE stmt FROM #sql1;
EXECUTE stmt;
END$$
DELIMITER ;
The Trigger
DELIMITER $$
USE `lms`$$
CREATE TRIGGER `lms`.`after_insert_into_leads`
AFTER INSERT ON `sets` FOR EACH ROW
BEGIN
CALL lms.leads_to_bak();
END$$
DELIMITER ;
The problem
I get a Error Code: 1336. Dynamic SQL is not allowed in stored function or trigger error message when making an INSERT which by implication would execute the trigger and the stored procedure. I am assuming the problem is the Dynamic SQL here:
PREPARE stmt FROM #sql1;
EXECUTE stmt;
I've looked around and there is a thread on stackoverflow on the problem, but no answer. Does anyone have any suggestions for a plausible workaround?
There is no good workaround for the absense of Dynamic SQL in MySQL functions, just klunky cludges. Some things still remain downright impossible to cludge, such as using a dynamically-calculated field name or table name in a SQL query. Yes, once in a while there is a need for doing this sort of thing!
And don't try cheat by putting the Dynamic SQL in a stored procedure and wrapping in a function or trigger, as the question poser tried - MySQL is too clever and will give you the usual obscure error message. Believe me, I have been around all the houses.
Coming from an Oracle PL/SQL and MS SQL Server background, I sorely miss the richness that PL/SQL and (to a small extent) T-SQL offers for writing procedural SQL.
Within the procedure definition, you need to store all your IN/OUT variables.
Change:
CREATE PROCEDURE `lms`.`leads_to_bak` ()
to:
CREATE PROCEDURE `lms`.`leads_to_bak` (
IN table1 varchar(32),
IN table2 varchar(32),
)
Then call doing this:
CALL `lms`.`leads_to_bak`('table1', 'table2')
replacing the strings with your own.
The purpose of using stored procedures is to prevent SQL injection using strictly typed data. You don't technically need to prepare it in the stored procedure if you ONLY send strictly typed input variables in the parameter list.
This way, you handle the string operations prior to the stored procedure call. Keep your stored procs skinny!
Here's an example of one of my stored procedures:
DELIMITER ;
DROP PROCEDURE IF EXISTS `save_player`;
DELIMITER //
CREATE PROCEDURE `save_player` (
IN uid int(15) UNSIGNED,
IN email varchar(100),
IN name varchar(100),
IN passwd char(96),
IN state ENUM('active','suspended','deleted'),
IN user_role ENUM('gamemaster','moderator','player'),
IN locale ENUM('en','fr'),
IN lvl tinyint(1),
IN hp bigint(20),
IN reborn tinyint(1),
IN cross_ref varchar(12),
IN email_verified tinyint(1),
OUT new_id int(15) UNSIGNED
)
BEGIN
DECLARE date_deleted timestamp DEFAULT NULL;
IF uid > 0 AND EXISTS (SELECT id FROM user WHERE `id`= uid) THEN
IF state = 'deleted' THEN
SET date_deleted = CURRENT_TIMESTAMP;
END IF ;
UPDATE `user` SET
`email` = email,
`name` = name,
`passwd` = passwd,
`state` = state,
`user_role` = user_role,
`locale` = locale,
`lvl` = lvl,
`hp` = hp,
`reborn` = reborn,
`cross_ref` = cross_ref,
`email_verified` = email_verified,
`date_deleted` = date_deleted
WHERE `id` = uid;
SET new_id = uid;
ELSE
INSERT INTO user (`email`, `name`, `passwd`, `state`, `user_role`, `locale`, `lvl`, `hp`, `reborn`, `cross_ref`, `email_verified`, `date_created`)
VALUES (email, name, passwd, state, user_role, locale, lvl, hp, reborn, cross_ref, email_verified, NOW());
SELECT LAST_INSERT_ID() INTO new_id;
END IF;
END //
DELIMITER ;
There’s not standard way to check if a MySQL user exists and based on that drop it. Are there any workarounds for this?
Edit: I need a straight way to run this without throwing up an error
e.g.
DROP USER test#localhost; :
This worked for me:
GRANT USAGE ON *.* TO 'username'#'localhost';
DROP USER 'username'#'localhost';
This creates the user if it doesn't already exist (and grants it a harmless privilege), then deletes it either way. Found solution here: http://bugs.mysql.com/bug.php?id=19166
Updates: #Hao recommends adding IDENTIFIED BY; #andreb (in comments) suggests disabling NO_AUTO_CREATE_USER.
Since MySQL 5.7 you can do a DROP USER IF EXISTS test
More info: http://dev.mysql.com/doc/refman/5.7/en/drop-user.html
To phyzome's answer (most highly voted one), it seems to me that if you put "identified by" at the end of the grant statement, the user will be created automatically. But if you don't, the user is not created. The following code works for me,
GRANT USAGE ON *.* TO 'username'#'localhost' IDENTIFIED BY 'password';
DROP USER 'username'#'localhost';
Hope this helps.
Found the answer to this from one of the MySQL forums. We’ll need to use a procedure to delete the user.
User here is “test” and “databaseName” the database name.
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ANSI';
USE databaseName ;
DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE databaseName.drop_user_if_exists()
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = 'test' and Host = 'localhost';
IF foo > 0 THEN
DROP USER 'test'#'localhost' ;
END IF;
END ;$$
DELIMITER ;
CALL databaseName.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_users_if_exists ;
SET SQL_MODE=#OLD_SQL_MODE ;
CREATE USER 'test'#'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES ON databaseName.* TO 'test'#'localhost'
WITH GRANT OPTION
Update
As of MySQL 5.7 you can directly use DROP USER IF EXISTS statement.
https://dev.mysql.com/doc/refman/5.7/en/drop-user.html
DROP USER IF EXISTS 'user'#'localhost';
FYI (and for older version of MySQL), this is a better solution...!!!
The following SP will help you to remove user 'tempuser'#'%' by executing CALL DropUserIfExistsAdvanced('tempuser', '%');
If you want to remove all users named 'tempuser' (say 'tempuser'#'%', 'tempuser'#'localhost' and 'tempuser'#'192.168.1.101') execute SP like CALL DropUserIfExistsAdvanced('tempuser', NULL); This will delete all users named tempuser!!! seriously...
Now please have a look on mentioned SP DropUserIfExistsAdvanced:
DELIMITER $$
DROP PROCEDURE IF EXISTS `DropUserIfExistsAdvanced`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `DropUserIfExistsAdvanced`(
MyUserName VARCHAR(100)
, MyHostName VARCHAR(100)
)
BEGIN
DECLARE pDone INT DEFAULT 0;
DECLARE mUser VARCHAR(100);
DECLARE mHost VARCHAR(100);
DECLARE recUserCursor CURSOR FOR
SELECT `User`, `Host` FROM `mysql`.`user` WHERE `User` = MyUserName;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET pDone = 1;
IF (MyHostName IS NOT NULL) THEN
-- 'username'#'hostname' exists
IF (EXISTS(SELECT NULL FROM `mysql`.`user` WHERE `User` = MyUserName AND `Host` = MyHostName)) THEN
SET #SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", MyUserName, "'#'", MyHostName, "'") AS mResult) AS Q LIMIT 1);
PREPARE STMT FROM #SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END IF;
ELSE
-- check whether MyUserName exists (MyUserName#'%' , MyUserName#'localhost' etc)
OPEN recUserCursor;
REPEAT
FETCH recUserCursor INTO mUser, mHost;
IF NOT pDone THEN
SET #SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", mUser, "'#'", mHost, "'") AS mResult) AS Q LIMIT 1);
PREPARE STMT FROM #SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END IF;
UNTIL pDone END REPEAT;
END IF;
FLUSH PRIVILEGES;
END$$
DELIMITER ;
Usage:
CALL DropUserIfExistsAdvanced('tempuser', '%'); to remove user 'tempuser'#'%'
CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101'); to remove user 'tempuser'#'192.168.1.101'
CALL DropUserIfExistsAdvanced('tempuser', NULL); to remove all users named 'tempuser' (eg., say 'tempuser'#'%', 'tempuser'#'localhost' and 'tempuser'#'192.168.1.101')
Um... Why all the complications and tricks?
Rather then using DROP USER... You can simply delete the user from the mysql.user table (which doesn't throw an error if the user does not exist), and then flush privileges to apply the change.
DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost';
FLUSH PRIVILEGES;
-- UPDATE --
I was wrong. It's not safe to delete the user like that. You do need to use DROP USER. Since it is possible to have mysql options set to not create users automatically via grants (an option I use), I still wouldn't recommend that trick. Here's a snipet from a stored procedure that works for me:
DECLARE userCount INT DEFAULT 0;
SELECT COUNT(*) INTO userCount FROM mysql.user WHERE User = userName AND Host='localhost';
IF userCount > 0 THEN
SET #S=CONCAT("DROP USER ", userName, "#localhost" );
PREPARE stmt FROM #S;
EXECUTE stmt;
SELECT CONCAT("DROPPED PRE-EXISTING USER: ", userName, "#localhost" ) as info;
END IF;
FLUSH PRIVILEGES;
DROP USER IF EXISTS 'user'#'localhost' ;
that works for me without throwing any errors in Maria DB, it should work for u too
Regarding #Cherian's answer, the following lines can be removed:
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ANSI';
...
SET SQL_MODE=#OLD_SQL_MODE;
...
This was a bug pre 5.1.23. After that version these are no longer required. So, for copy/paste convenience, here is the same with the above lines removed. Again, for example purposes "test" is the user and "databaseName" is the database; and this was from this bug.
DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE databaseName.drop_user_if_exists()
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = 'test' and Host = 'localhost';
IF foo > 0 THEN
DROP USER 'test'#'localhost' ;
END IF;
END ;$$
DELIMITER ;
CALL databaseName.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_users_if_exists ;
CREATE USER 'test'#'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES ON databaseName.* TO 'test'#'localhost'
WITH GRANT OPTION
I wrote this procedure inspired by Cherian's answer.
The difference is that in my version the user name is an argument of the procedure ( and not hard coded ) . I'm also doing a much necessary FLUSH PRIVILEGES after dropping the user.
DROP PROCEDURE IF EXISTS DropUserIfExists;
DELIMITER $$
CREATE PROCEDURE DropUserIfExists(MyUserName VARCHAR(100))
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = MyUserName ;
IF foo > 0 THEN
SET #A = (SELECT Result FROM (SELECT GROUP_CONCAT("DROP USER"," ",MyUserName,"#'%'") AS Result) AS Q LIMIT 1);
PREPARE STMT FROM #A;
EXECUTE STMT;
FLUSH PRIVILEGES;
END IF;
END ;$$
DELIMITER ;
I also posted this code on the CodeReview website ( https://codereview.stackexchange.com/questions/15716/mysql-drop-user-if-exists )
DROP USER 'user'#'localhost';
The above command will drop the user from the database, however, it is Important to know if the same user is already using the database, that session will not end until the user closes that session. It is important to note that dropped user will STILL access the database and perform any operations.
DROPPING THE USER DOES NOT DROP THE CURRENT USER SESSION
Combining phyzome's answer (which didn't work right away for me) with andreb's comment (which explains why it didn't) I ended up with this seemingly working code that temporarily disables NO_AUTO_CREATE_USER mode if it is active:
set #mode = ##SESSION.sql_mode;
set session sql_mode = replace(replace(#mode, 'NO_AUTO_CREATE_USER', ''), ',,', ',');
grant usage on *.* to 'myuser'#'%';
set session sql_mode = #mode;
drop user 'myuser'#'%';
in terminal do:
sudo mysql -u root -p
enter the password.
select user from mysql.user;
now delete the user 'the_username'
DROP USER the_unername;
replace 'the_username' with the user that you want to delete.
In case you have a school server where the pupils worked a lot. You can just clean up the mess by:
delete from user where User != 'root' and User != 'admin';
delete from db where User != 'root' and User != 'admin';
delete from tables_priv;
delete from columns_priv;
flush privileges;
If you mean you want to delete a drop from a table if it exists, you can use the DELETE command, for example:
DELETE FROM users WHERE user_login = 'foobar'
If no rows match, it's not an error.