Use stored procedure to add users to database - mysql

I'm trying to create a stored procedure that can grant users access to a database. The idea is that the procedure would take in one parameter (the given username) and then give the user access to a database. So, that normal Mariadb query to do this is:
GRANT ALL ON databaseNameHere.* TO 'userNameHere'#'%';
The problem is, 'userNameHere' needs to be in quotes to perform this query so I need to concatenate quotes to the given user name parameter.
I thought to do this with DECLARE as so:
DELIMITER $$
CREATE PROCEDURE GrantUserAccess(IN as_username CHAR(25))
BEGIN
SET #sql = CONCAT("GRANT ALL ON archimodels.* TO '" as_username "'#'%'")
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
I keep running into error statement:
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near '"'#'%'") PREPARE stmt FROM #sql; EXECUTE stmt; DEALLOCATE
PREPARE stmt; EN' at line 3
Here's an example of what I want to do, the only problem is I need to concatenate quotes to the username
https://www.oreilly.com/library/view/mysql-stored-procedure/0596100892/re39.html

There's a couple of things wrong.
1) The "smart quotes" curly quote and double quote characters in place of ASCII quote and double quote characters
2) to include the contents of a procedure parameter or variable in the text of a SQL statement, we'd need to use dynamic SQL PREPARE/EXECUTE/DEALLOCATE
We also need to ensure that the parameter passed in is valid; the GRANT statement is going to create user with no password if the user doesn't exist. And if the parameter happens to include a single quote character, that's going to break our SQL if we don't escape it. We might also consider using the TRIM() function to remove any leading or trailing spaces from the parameter.
Something like this:
DELIMITER $$
CREATE PROCEDURE GrantUserAccess(IN as_username CHAR(25))
BEGIN
SET #sql = CONCAT('GRANT ALL ON databaseNameHere.* TO '''
,REPLACE(as_username,'''','''''')
,'''#''%''' );
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = '';
END$$
DELIMITER ;

Related

Execute sql using a stored procedure in mysql

I have the following stored procedure. The idea is to get a list of databases and execute an sql statement.
DELIMITER $$
CREATE PROCEDURE updateMySQL (
IN theSQL varchar(4000)
)
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE theDatabases varchar(100) DEFAULT "";
-- declare cursor for employee email
DEClARE curDatabase
CURSOR FOR
SELECT schema_name FROM information_schema.schemata where SCHEMA_NAME = 'mydb' order by 1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
OPEN curDatabase;
getDatabase: LOOP
FETCH curDatabase INTO theDatabases;
IF finished = 1 THEN
LEAVE getDatabase;
END IF;
-- build email list
-- SET emailList = CONCAT(theDatabases,";",emailList);
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
END LOOP getDatabase;
CLOSE curDatabase;
END$$
DELIMITER ;
I am attempting to execute the stored procedure like this,
SET #theSQL = 'ALTER VIEW `Reports` AS
SELECT DISTINCT
`tableA`.`Id` AS `Id`,
`tableA`.`letterId` AS `letterId`
FROM
`mytable` `tableA`
ORDER BY 1';
call updateMySQL(#theSQL);
EDIT There was an error on executing the procedure,
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 'NULL' at line 1
I am using mysql 8.0.17
Investigate carefully MySQL 8.0 Reference Manual / SQL Statements / Prepared Statements, the section "SQL Syntax Allowed in Prepared Statements".
This section claims FULL list of statements which are allowed in Prepared statements. ALTER VIEW is NOT listed. So it is NOT allowed.
Use DROP VIEW and CREATE VIEW instead.
Always receive and investigate all error messages.
You should change this part
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
to this:
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement; /* don't forget to deallocate */
/* there's a difference between the variables #theSQL and theSQL (your parameter) */
/* IIRC prepare statements need user defined variables or a syntax error occurs. Therefore I simply assign the parameter to a user-defined variable */
SET #theSQL = theSQL;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement;
Read more about user-defined variables here: https://dev.mysql.com/doc/refman/8.0/en/user-variables.html
Here the differences are explained: https://stackoverflow.com/a/1010042/447489
When you don't initialize them, their content is just NULL. Since there's a difference between user-defined variables and local variables (and also your parameter variable), your current solution did nothing.

Pass a procedure name dynamically

Is it possible to pass a name of a procedure dynamically within another procedure?
The procedure name is stored in a table and based on criteria the name will be different.
If it is possible how would I accomplish this?
So far I have something like this:
SET $proc = CONCAT('CALL ',$queryString);
PREPARE stmt FROM CONCAT('CALL ', $queryString);
EXECUTE stmt;
Pretty close, just use correct prepared statement syntax:
create procedure sp_exec_proc(
in_proc char(64)
)
begin
set #proc = concat('CALL ',in_proc);
prepare stmt from #proc;
execute stmt;
end
You can then pass in the procedure name and optional parameters
call sp_exec_proc('sp_my_proc("ABC")')

MySQL stored procedure that accepts string with multiple parameters

I want to create a stored procedure which accepts all the values in the IN parameter as a single string.
DELETE FROM object
WHERE Type NOT IN
('ListGrid',
'TextField',
'SpinBox',
'MenuButton',
'ListGrid',
'RadioButton',
'DropDown',
'PopUp',
'Element',
'Checkbox',
'TreeDropDown',
'TblColumn',
'Button',
'Link',
'Filter',
'TblRow',
'GridRow',
'Popup')
This is an example of one I've tried but it does not work.
DELIMITER //
CREATE PROCEDURE deleteObjectTypes(IN p_type VARCHAR(255))
BEGIN
SET #query = CONCAT ('DELETE FROM object WHERE Type NOT IN (',p_type,')');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
I get the following error:
#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 ''List)' at line 1
When running this query:
CALL deleteObjectTypes("'ListGrid1','TextField1','SpinBox1','MenuButton1','ListGrid2','TextField2','SpinBox2','MenuButton2','ListGrid3','TextField3','SpinBox3','MenuButton3','ListGrid4','TextField4','SpinBox4','MenuButton4','ListGrid5','TextField5','SpinBox5','MenuButton5','ListGrid6','TextField6','SpinBox6','MenuButton6'")
You need to change the VARCHAR size to it's maximum value (or a lower significant value).
DELIMITER //
CREATE PROCEDURE deleteObjectTypes(IN p_type VARCHAR(65535))
BEGIN
SET #query = CONCAT ('DELETE FROM object WHERE Type NOT IN (',p_type,')');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
However, note that the limit is lower if you use a multi-byte character set:
VARCHAR(21844) CHARACTER SET utf8
As seen here.
(sorry i cannot add comments too low reputation)
Your procedure looks ok, maybe the problem is somewhere else? note that we have defined as a varchar 255 characters and the example you provided more than this number (291 characters)
You should give this a try (shortened example):
DELETE
FROM
object
WHERE
NOT FIND_IN_SET( Type, 'ListGrid,TextField,SpinBox,MenuButton,ListGrid' );
and with stored procedure
DELIMITER //
CREATE PROCEDURE deleteObjectTypes(IN p_type VARCHAR(255))
BEGIN
DELETE
FROM
object
WHERE
NOT FIND_IN_SET( Type, p_type );
END //
DELIMITER ;
CALL deleteObjectTypes( 'ListGrid1,TextField1,SpinBox1,MenuButton1,ListGrid2,TextField2,SpinBox2,MenuButton2,ListGrid3,TextField3,SpinBox3,MenuButton3,ListGrid4,TextField4,SpinBox4,MenuButton4,ListGrid5,TextField5,SpinBox5,MenuButton5,ListGrid6,TextField6,SpinBox6,MenuButton6' );

Mysql stored procedure

What I want to do is,create a table in mysql by passing the table name as a parameter in the stored procedure.I'm using following code for stored procedure in mysql.
DELIMITER //
CREATE PROCEDURE createtable(IN tablename varchar(20))
BEGIN
SET #s=CONCAT('CREATE TABLE', tablename, '(month varchar(20))');
PREPARE stmt FROM #s;
EXECUTE stmt;
END //
and when i call it
CALL createtable('account');
I get the following error
You have an error in your SQL syntax; check the MySQL server version for the right syntax to us...
I don't know where I'm wrong..
You forgot the spaces before and after your table name. Try
DELIMITER //
CREATE PROCEDURE createtable(IN tablename varchar(20))
BEGIN
SET #s=CONCAT('CREATE TABLE ', tablename, ' (month varchar(20))');
PREPARE stmt FROM #s;
EXECUTE stmt;
END //

syntax error with concat and limit in mysql

I am getting syntax error on runnning this. Is it possible to use variables with limit without using concat function?
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ',_start,_end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Error is
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 '_qry;
EXECUTE stmt;
You missed , before the offset.
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
I think you have to change the DEFAULT DELIMITER first and adding PARAMETER DIRECTION before creating the STORED PROCEDURE.
There are good reasons to use prepared statements:
1. ) Save on query parsing
2.) Save on data conversion and copying
3.) Avoid SQL Injection
4.) Save memory on handling blobs
There are also drawbacks and chewats of using prepared statements:
1.) Query cache does not work
2.) Extra server round trip required if statement used only once
3.) Not all statements can be prepared. So you can’t use prepared API
exclusively you’ll need to fall back to normal API for some statements
4.) Newer and sometimes buggy code. I had a lot of problems with PHP
prepared statements. It is getting better but still it is less mature
than standard API
5.) You can’t use placeholders in place of all identifiers. For example you
can’t use them for table name. In certain version it even does not work for
LIMIT boundaries
6.) Inconvenient list handling. Unlike in for example PEAR emulated prepard
statements there is no nice way to pass list of values to IN
7.) Harder tracing. Logs were now fixed to include full statement text not
only “Execute” but in SHOW INNODB STATUS you would still see statements
without actual values – quite inonvenient for analyses.
try this one:
UPDATE 1
DELIMITER $$
CREATE PROCEDURE SP(IN _start INT,IN _end INT)
BEGIN
SET #iQuery = CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM #iQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
MySQL Syntax for Prepared Statements
delimiter //
drop procedure if exists SP //
create procedure SP(_start int,_end int)
begin
declare _qry varchar(500);
set #_qry = 'select * from tbl limit ?, ?';
set #start = _start;
set #end = _end;
prepare stmt from #qry;
execute stmt using #start, #end;
deallocate prepare stmt;
end; //
delimiter ;
call SP(1,2);