I've created a stored procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `zero`.`sp_for_insert_into_account_db`$$
CREATE PROCEDURE `zero`.`sp_for_insert_into_account_db` (usr_key char(6),usr_name varchar(15),usr_password varchar(15),OUT output_message INT)
BEGIN
DECLARE no_of_row INT;
SELECT COUNT(*) INTO no_of_row from account_db;
IF no_of_row < 4 THEN
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (',usr_key,usr_name,usr_password,')');
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET output_message=1;
ELSE
SET output_message=0;
END IF;
END$$
DELIMITER ;
I'm calling it with query
call sp_for_insert_into_account_db('a','b','c',#output_ message);
The error is like:
Column count does not match value...
I'm passing 4 arguments...
Why is this error occurring?
I've already checked with this syntax (by default parameter is IN type)
sp_for_insert_into_account_db(IN usr_key char(6),
IN usr_name varchar(15),
IN usr_password varchar(15),
OUT output_message INT)
Problem is also here:
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (',usr_key,usr_name,usr_password,')');
You are trying to insert 3 values and the concatenation returns 1
use this instead:
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (\'',usr_key,'\',\'',usr_name,'\',\'',usr_password,'\')');
Not entirely sure why you're using prepared statements/dynamic sql when you dont need to ?? See the following example which i've cleaned up for you a little:
drop procedure if exists sp_for_insert_into_account_db;
delimiter #
create procedure sp_for_insert_into_account_db
(
in p_usr_key char(6),
in p_usr_name varchar(15),
in p_usr_pwd varchar(15),
out p_output_message tinyint unsigned
)
begin
declare v_no_of_row int unsigned default 0;
set p_output_message=0;
select count(*) into v_no_of_row from account_db;
if v_no_of_row < 4 then
insert into account_db(usr_key, usr_name, usr_pwd) values (p_usr_key, p_usr_name, p_usr_pwd);
set p_output_message = 1;
end if;
end#
delimiter ;
call sp_for_insert_into_account_db (...);
EDIT
are you a COBOL PROGRAMMER FROM THE 1970'S AND IS THAT WHY YOU HAVE TO USE CAPS ?
Related
I am using MySQL -actually MariaDB from PHPMyAdmin- and trying to write an insert inside a stored procedure and for obvious (security) reasons it is not allowed.
I tried to change the permissions using the GRANT EXECUTE ON PROCEDURE statement.
GRANT EXECUTE ON PROCEDURE test.putDataInFull TO 'root'#'localhost'
I have really hit a wall here, any ideas?
edit:
DELIMITER //
CREATE PROCEDURE putDataInFull (IN matchid INT(11))
BEGIN
DECLARE koula int(11);
DECLARE c varchar(255);
SET #koula = matchid;
SET #c := concat('insert into log (match_id, comment) values (?,\'inPUtDataWeTrtust\');');
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT CONCAT(#c, ' is not valid');
END;
PREPARE stmt FROM #c;
EXECUTE stmt USING #koula;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
p.s. this is not a production project, just fun, so I really do not care about security.
You can create an insert with your variables. It is not necessary to create a magic string. Here you get an other example of an other stackoverflow question:
DELIMITER $$
CREATE PROCEDURE ADD_WITHDRAWAL_A(IN withdrawalcode_p VARCHAR(25), IN id_p VARCHAR(8), IN amount_p VARCHAR(12), IN datewithdrawn_p VARCHAR(35), IN approved_p VARCHAR(8))
BEGIN
START TRANSACTION;
INSERT INTO Withdrawals(WithdrawalCode, IDD, Amount, DateWithdrawn, Approved)
VALUES (withdrawalcode_p, id_p, amount_p, datewithdrawn_p, approved_p);
UPDATE account SET AccountBalance = AccountBalance - amount_p WHERE IDD = id_p LIMIT 1;
COMMIT;
END $$
DELIMITER ;
I do my filter with column of table pass through parameter(field after where in line 7) procedure but pass parameter column of table ,mysql doesn't know
use testphantrang;
DELIMITER $$
CREATE PROCEDURE `filter`(in field varchar(40), in giatri varchar(40),in index_of_page int)
begin
declare xx int ;
set xx = index_of_page*15;
SELECT * from test where field like CONCAT('%', giatri,'%') limit xx,15;
END; $$
DELIMITER ;
call `filter`('email','b',0);
Below is my table:
DELIMITER $$
CREATE PROCEDURE `filter`(in field varchar(40), in giatri varchar(40),in index_of_page int)
begin
declare xx int ;
set xx = index_of_page*15;
set #query = CONCAT('SELECT * from test where field rlike ''', giatri,''' limit ',xx,',15;');
PREPARE dynamic_statement FROM #query;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement;
END; $$
DELIMITER ;
call `filter`('email','b',0);
I am trying to do the following and I am wondering if that is possible in MySQL:
CREATE PROCEDURE `sp_test`(
ulon int(4),
usrname varchar(20),
usrst varchar(20),
usrdt varchar(10)
)
BEGIN
DECLARE bid int(11);
START TRANSACTION;
SELECT t_bid INTO bid FROM generalb WHERE dt=usrdt;
INSERT
INTO
rslt
(
rbid,
rusrname,
rusrst,
usrdt
)
VALUES
(
bid,
usrname,
usrst,
usrdt
);
call sp_nextproc_13(bid, ulon);
COMMIT;
END;
Look at this line:
call sp_nextproc_13(bid, ulon);
How could I achieve something like this:
call sp_nextproc_#bid(bid, ulon);
I need to be able to call a procedure dynamically as I do not know the name of the procedure until I get the bid. If anyone knows the answer, thanks so much
LATEST UPDATE:
I have made the following changes:
CREATE PROCEDURE `sp_test`(
ulon int(4),
usrname varchar(20),
usrst varchar(20),
usrdt varchar(10)
)
BEGIN
DECLARE bid int(11);
START TRANSACTION;
SELECT t_bid INTO bid FROM generalb WHERE dt=usrdt;
INSERT
INTO
rslt
(
rbid,
rusrname,
rusrst,
usrdt
)
VALUES
(
bid,
usrname,
usrst,
usrdt
);
SET #sql=concat('call sp_nextproc_',bid,'(?,?)');
PREPARE stmt FROM #sql;
SET #var1=bid;
SET #var2=ulon;
EXECUTE stmt USING #var1, #var2;
COMMIT;
END;
IF I hardcode some values, it works. However if I don't, it doesn't. Please see below:
If I call:
CALL sp_test(2, 'John','test','AAAA');
ERROR here:
SELECT t_bid INTO bid FROM generalb WHERE dt=usrdt;
Column t_bid cannot be null
If I hardcode the value like this:
SELECT t_bid INTO bid FROM generalb WHERE dt='AAAA';
The error disappears.
The second error is at the following line:
SET #var1=bid;
SET #var2=ulon;
EXECUTE stmt USING #var1, #var2;
ERROR missing value #var1 and #var2.
If I hardcode var1 and var2, it works:
SET #var1=13;
SET #var2=2;
EXECUTE stmt USING #var1, #var2;
I tried using # and without it on the variables but that didn't work. What I am doing wrong? :(
delimiter $$
create procedure sp_test
(
ulon int(4)
)
BEGIN
DECLARE bid int(11);
set bid=8888;
...
...
...
...
set #sql=concat('call sp_nextproc_',bid,'(?,?)');
prepare stmt from #sql;
set #var1=bid;
set #var2=ulon;
EXECUTE stmt using #var1,#var2;
END
$$
-- ------------
delimiter $$
CREATE PROCEDURE `sp_nextproc_8888`(
IN bid int(11),
IN ulon int(4)
)
BEGIN
select bid,ulon;
END
$$
-- test with these:
-- call sp_test(9999);
-- call sp_nextproc_8888(111,222);
I'm writing a stored procedure. I am having some problems using a variable in combination with LIMIT and a prepared statement. (See code below)
The procedure is created normally, but when I call it I get an error that variable a is undeclared. Any suggestions?
delimiter //
drop procedure if exists shop1;
create procedure shop1()
begin
declare a varchar(255) default null;
declare counter int(4) default 0;
declare row_numbers int(4);
declare s varchar(255) default null;
select count(*) into row_numbers from salesmen;
WHILE counter< row_numbers+1 DO
set #s='select fio from salesmen into a Limit ? 1';
set #counter=counter;
prepare stmt from #s;
execute stmt using #counter;
SET counter=counter+1;
insert into warehouse.place (shop, fio) values (1, a);
END WHILE;
SET counter=0;
select count(*) into row_numbers from products;
WHILE counter< row_numbers+1 DO
SET counter=counter+1;
END WHILE;
end;
//
You could use an INSERT ... SELECT to do the same thing -
INSERT INTO warehouse.place (shop, fio)
SELECT 1, fio FROM salesmen
Did you mean?
set #s='select fio from salesmen into a Limit ?,1';
I have two inputs for my stored procedure. One is the 'RoledID' and second one is the 'MenuIDs'. 'MenusIDs' is a list of comma separated menus ids that need to be inserted with RoledID. RoleId is just an INT and we need to put this RoledID against each MenuID. My table 'RolesMenus' contains two columns one for MenuID and one for RoleID.
Now I need to split MenuIDs and insert each MenuID with RoleID.
How can I write a stored procedure for it?
You can build one INSERT query (because statement allows to insert multiple records) and run it with prepared statements, e.g. -
SET #MenuIDs = '1,2,3';
SET #RoledID = 100;
SET #values = REPLACE(#MenuIDs, ',', CONCAT(', ', #RoledID, '),('));
SET #values = CONCAT('(', #values, ', ', #RoledID, ')'); -- This produces a string like this -> (1, 100),(2, 100),(3, 100)
SET #insert = CONCAT('INSERT INTO RolesMenus VALUES', #values); -- Build INSERT statement like this -> INSERT INTO RolesMenus VALUES(1, 100),(2, 100),(3, 100)
-- Execute INSERT statement
PREPARE stmt FROM #insert;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
As you see, it can be done without stored procedure.
Give this a go. It may need some tweaking if the MenuIDs string does not conform to 'menuId,menuId,menuId'.
Also I do not know what data type the menuId column is in your target table (INT?) so you may have to put some numeric checking in too (in case '1,2,3,banana,4,5' is passed in as the MenuIds input parameter).
DELIMITER $$
DROP PROCEDURE IF EXISTS `insert_role_menuids`$$
CREATE PROCEDURE `insert_role_menuids`(IN RoleID INT,IN MenuIDs varchar(500))
BEGIN
declare idx,prev_idx int;
declare v_id varchar(10);
set idx := locate(',',MenuIDs,1);
set prev_idx := 1;
WHILE idx > 0 DO
set v_id := substr(MenuIDs,prev_idx,idx-prev_idx);
insert into RolesMenus (RoleId,MenuId) values (RoleID,v_id);
set prev_idx := idx+1;
set idx := locate(',',MenuIDs,prev_idx);
END WHILE;
set v_id := substr(MenuIDs,prev_idx);
insert into RolesMenus (RoleId,MenuId) values (RoleID,v_id);
END$$
DELIMITER ;
for this solution, you must create a table with the name split_table, it can have a id(autoincrement) if you need it and must have a column where to store the value (I call it valor)
DELIMITER $$
USE `dbaname`$$
DROP PROCEDURE IF EXISTS `Split`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `Split`(
IN cadena VARCHAR(8000),
IN delimitador VARCHAR(10)
)
BEGIN
TRUNCATE split_table;
SET #posicion = 1;
SET #ldel = LENGTH(delimitador);
SET #valor = SUBSTRING_INDEX(cadena, delimitador, 1);
WHILE #valor <> '' AND #posicion > 0 DO
SET #valor = SUBSTRING_INDEX(cadena, delimitador, 1);
INSERT INTO split_table(valor) VALUES (#valor);
SET #posicion = POSITION(delimitador IN cadena);
SET #largo = LENGTH(cadena);
IF #largo >= #posicion THEN
SET cadena = SUBSTR(cadena, #posicion + #ldel, #largo - #posicion);
SET #valor = SUBSTRING_INDEX(cadena, delimitador, 1);
ELSE
SET #posicion = 0;
END IF;
END WHILE;
END$$
DELIMITER ;
First create procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `split_str_save_to_tmp_table`(
IN _str TEXT,
IN _table_name VARCHAR(80)
)
BEGIN
#DROP FIRST OLD TABLE
SET #q = CONCAT('DROP TEMPORARY TABLE IF EXISTS ', _table_name);
PREPARE st FROM #q;
EXECUTE st;
#CREATE TABLE
SET #q = CONCAT('CREATE TEMPORARY TABLE ', _table_name, '(id INT UNSIGNED NOT NULL PRIMARY KEY (id) )' );
PREPARE st FROM #q;
EXECUTE st;
SET #ids = REPLACE(_str, ',', '),(');
SET #ids = CONCAT('(', #ids, ')');
#INSERT INTO TABLE
SET #q = CONCAT('INSERT INTO ' , _table_name ,' VALUES');
SET #q = CONCAT(#q, #ids);
PREPARE st FROM #q;
EXECUTE st;
DEALLOCATE PREPARE st;
END
Then call
call split_str_save_to_tmp_table('1,2,3,4,5', 'tmp_split_product');
SELECT * FROM tmp_split_product
AFAIK MySQL does not have a function to split strings. Here is the MySQL manual for string related functions. In the comments section should be some information about workarounds for splitting string with substring-functions but not really usable:
MySQL manual