Error in syntax in PREPARE statement MYSQL - mysql

I've got a problem with my MYSQL script. When i try to execute it, MYSQL Workbench send me info that ive got problem with syntax near "int" . Any ideas?
DROP TABLE IF EXISTS Sprzedaz;
DROP PROCEDURE IF EXISTS odwrocenie;
CREATE TABLE IF NOT EXISTS Sprzedaz
(Towar VARCHAR(30), Miesiac VARCHAR(20), Wartosc INT);
INSERT INTO Sprzedaz VALUES('Buty', 'styczen', 230);
INSERT INTO Sprzedaz VALUES('Buty', 'styczen', 100);
INSERT INTO Sprzedaz VALUES('Koszula', 'styczen', 50);
INSERT INTO Sprzedaz VALUES('Koszula', 'luty', 80);
INSERT INTO Sprzedaz VALUES('Krawat', 'marzec', 190);
DELIMITER //
CREATE PROCEDURE odwrocenie()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE miesiac_var VARCHAR(20);
DECLARE miesiac_kursor CURSOR FOR SELECT Miesiac FROM Sprzedaz GROUP BY Miesiac;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN miesiac_kursor;
read_loop: LOOP
FETCH miesiac_kursor INTO miesiac_var;
IF done THEN
LEAVE read_loop;
END IF;
PREPARE sql_query FROM 'ALTER TABLE Sprzedaz ADD COLUMN ? INT';
EXECUTE sql_query USING #miesiac_var;
END LOOP;
CLOSE miesiac_kursor;
DEALLOCATE PREPARE sql_query;
END
//
DELIMITER ;
CALL odwrocenie();

Related

MariaDB does not do Execute Insert in Procedure

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 ;

Using a variable to reference another database in SELECT statement

I am trying to cycle through all rows in a table that holds the database name for another database. This is what I have which compiles but doesn't work as MySQL takes the 'database' bit as the actual database name rather than the contents.
How can I change the following so that it takes the contents of the variable?
DROP PROCEDURE IF EXISTS CYCLE;
DELIMITER ;;
CREATE PROCEDURE CYCLE()
BEGIN
DECLARE data_name CHAR(255);
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_i CURSOR FOR SELECT database FROM company;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO database;
IF done THEN
LEAVE read_loop;
END IF;
SELECT * FROM database.table LIMIT 1;
END LOOP;
CLOSE cursor_i;
END;
;;
DELIMITER ;
Update: to be clear I know that 'database' is a reserved word. I have used that here in place of the actual variable name I have used.
You can't evaluate the content on a variable on a table select statement, in that case you must build a query in a string an execute:
DROP PROCEDURE IF EXISTS CYCLE;
DELIMITER ;;
CREATE PROCEDURE CYCLE()
BEGIN
DECLARE data_name CHAR(255); -- unused?
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_i CURSOR FOR SELECT database_name FROM company;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO data_name;
IF done THEN
LEAVE read_loop;
END IF;
-- now build the query before execute:
set #sql = concat('SELECT * FROM `',data_name,'`.`your_table` LIMIT 1');
-- and execute
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt ;
END LOOP;
CLOSE cursor_i;
END;
;;
DELIMITER ;
*Would better not confusing us using variable names that causes more questions. #JustSaying

How to update column in every table which name starts with special characters

I need to update special column in every table that which name start with :-
`REPORT_<"DATE PATERN">`
How actually I can do it?.
upd:
I've tried to write stored procedure, but I'm not familiar with it, so it does not work:
DELIMITER $$
DROP PROCEDURE IF EXISTS `debug_msg`$$
CREATE PROCEDURE debug_msg(enabled INTEGER, msg VARCHAR(255))
BEGIN
IF enabled THEN BEGIN
select concat("** ", msg) AS '** DEBUG:';
END; END IF;
END $$
DELIMITER $$
DROP PROCEDURE IF EXISTS changeColumnType;
CREATE PROCEDURE changeColumnType ()
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE tableName varchar(100);
DEClARE table_cursor CURSOR FOR
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME LIKE '%REPORT_%';
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN table_cursor;
get_tableName: LOOP
FETCH table_cursor INTO tableName;
IF v_finished = 1 THEN
LEAVE get_tableName;
END IF;
call debug_msg(1, tableName);
ALTER TABLE tableName MODIFY COLUMN TIME VARCHAR(8);
END LOOP get_tableName;
CLOSE table_cursor;
END$$
DELIMITER ;
I have the following error:
ERROR 1146 (42S02): Table 'test.tablename' doesn't exist.
I fails on this step ALTER TABLE tableName MODIFY COLUMN TIME VARCHAR(8);
Resolved it by adding prepared statement
SET #table = tableName;
SET #s1 = CONCAT('ALTER TABLE ', #table, ' MODIFY COLUMN TIME VARCHAR(8);');
PREPARE stmt FROM #s1;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Cursor in Procedure does not return any values

I have a database where temp tables are created, those table names are randomly generated and saved in Checkouts.unid. I want to drop all those tables and truncate the table Checkouts. I thought the niftiest solution would be a procedure, but it will not work:
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE `t` VARCHAR(64);
DECLARE `ch` CURSOR FOR SELECT `unid` FROM `Checkouts`;
OPEN `ch`;
drop_tables: LOOP
FETCH `ch` INTO `t`;
DROP TABLE IF EXISTS `t`;
END LOOP;
CLOSE `ch`;
TRUNCATE TABLE `Checkouts`;
END
I always get "No data - zero rows fetched, selected, or processed" although those tables are there and the table Checkouts is not empty though.
You have to add something like this in order to end your loop:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET ...;
See example in the documentation.. E.g. ...
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE `t` VARCHAR(64);
DECLARE `ch` CURSOR FOR SELECT `unid` FROM `Checkouts`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN `ch`;
drop_tables: LOOP
FETCH `ch` INTO `t`;
IF done THEN
LEAVE drop_tables;
END IF;
DROP TABLE IF EXISTS `t`;
END LOOP;
CLOSE `ch`;
TRUNCATE TABLE `Checkouts`;
END
Otherwise you will get an error once you reached the end of your cursor.
I got it working with this:
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE done int DEFAULT 0;
DECLARE t CHAR(64);
DECLARE ch CURSOR FOR SELECT `unid` FROM `Checkouts`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN ch;
drop_table: LOOP
FETCH ch INTO t;
IF done = 1 THEN
LEAVE drop_table;
END IF;
SET #sql := CONCAT('DROP TABLE IF EXISTS `', t, '`');
PREPARE dropt FROM #sql;
EXECUTE dropt;
END LOOP;
CLOSE ch;
TRUNCATE TABLE `Checkouts`;
END;
CALL spCheckoutsCleanup;

Error in stored procedure - column count does not match value

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 ?