I have a series of 16 PREPARE, EXECUTE and DEALLOCATE statements (in a stored procedure), each inserting rows into a diffterent table (table 1 to table16). eg:
SET #Command1 = CONCAT("insert into TABLE1" , ...etc.. );
PREPARE stmt1 FROM #Command1 ;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #Command1 = CONCAT("insert into TABLE2" , ...etc.. );
PREPARE stmt1 FROM #Command1 ;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
.
.
.
SET #Command1 = CONCAT("insert into TABLE16" , ...etc.. );
PREPARE stmt1 FROM #Command1 ;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
When I execute the stored procedure, the INSERT works intermittently. Sometimes all the 16 inserts works, but sometimes they don't.
In the last CALL of the stored procedure, the first 2 inserts (into TABLE1 and TABLE2 ) and the last 4 inserts (TABLE 13 to 16) work, but not the inserts into Table 3 to 12.
Can you explain why? Can't be because I'm using the same variable/handle command1 and stmt1?
In MySQL, the combinations of Prepare and Execute commands should be used with placeholders - saving you time with concat strings (maybe one of your concats simply goes wrong) and of course - prevent sql injections (yey!)
So... just build your statements like this one:
-- in MySQL ? is a placeholder
set #sampleQuery = 'select name into #testValue from myTable where id = ?';
set #idParam = 'NT54X9';
prepare sampleStatement from #sampleQuery;
execute sampleStatement using #idParam; -- `using` is the key point here
deallocate prepare sampleStatement;
select #testValue
Related
I am using phpMyAdmin to try to schedule an event that runs every hour. I need it to select data from one of my tables and export it to csv that has a unique name which includes the current timestamp. Outside of an event, I can successfully output from my table to a csv like so:
SET #TimeStamp = DATE_FORMAT(NOW(),'__%Y_%m_%d__%H.%i.%s');
SELECT CONCAT(
'SELECT form_value INTO OUTFILE \'D:/Websites/RTP/contact_form_data/form_data_',
#TimeStamp,
'.csv\' ',
'FROM wp_db7_forms'
) INTO #SQL;
PREPARE stmt from #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
However, I can't for the life of me figure out how to get this working in an event. phpMyAdmin doesn't give very specific error messages, but it seems that the event doesn't like the fact that I am using a variable (it also doesn't seem to like CONCAT). From my research, I've found that this may be because each event executes in a new session, and user-defined variables have session scope.
I tried creating a stored procedure to execute this same block of code, but that experiences similar issues.
Any ideas on an approach I can take to get my code to properly execute in an event?
Try this.
SET #sql =
CONCAT(
'SELECT form_value INTO OUTFILE \'D:/Websites/RTP/contact_form_data/form_data_',
DATE_FORMAT(NOW(),'__%Y_%m_%d__%H.%i.%s'),
'.csv\' ',
'FROM wp_db7_forms'
) ;
PREPARE stmt from #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
The session variable for time is not needed and the session variable #sql must be set as show in the code
This can be saved in mysql 8 and Workbench
DELIMITER $$
CREATE EVENT export_contact_Form_data
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
ON COMPLETION PRESERVE
DO BEGIN
SET #sql =
CONCAT(
'SELECT form_value INTO OUTFILE \'D:/Websites/RTP/contact_form_data/form_data_',
DATE_FORMAT(NOW(),'__%Y_%m_%d__%H.%i.%s'),
'.csv\' ',
'FROM wp_db7_forms'
) ;
PREPARE stmt from #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
This runs only once in one minute, so that you can i peace check
every thing
and of course the delete query
DROP EVENT IF Exists export_contact_Form_data;
if I want to call a procedure with different input in each time input1,input2, input 3, ... and different output out1,out2,...and so on
proc(input1,out1) proc(input2,out2)...
can I made only one prepared statement inside a while loop to do that job? something like this
while c <= 10 DO
SET #sql = CONCAT('call proc(input',c,',out',c')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set c=c+1;
end while;
If I have the output of a prepared statement; how do I use it as the source of my query?
CALL `myProcedure`;
PREPARE stmnt FROM #allSQL;
EXECUTE stmnt;
DEALLOCATE PREPARE stmnt;
So, I get an output from the EXECUTE stmnt; (let's call it tmp) and I would like to run a query along the lines of:
SELECT * FROM (EXECUTE stmnt) AS tmp WHERE this = that;
You could prepare a CREATE TEMPORARY TABLE statement that contains the result of the query:
SET #createSQL = CONCAT('CREATE TEMPORARY TABLE tmp AS ', #allSQL);
PREPARE stmt FROM #createSQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT * FROM tmp WHERE this = that;
OK I have this code in a stored procedure:
SET #qry = CONCAT('UPDATE ', usermeta_table, ' SET meta_value = ', #token_count, ' WHERE user_id = ', #temp_id, ' AND meta_key = "token_count"');
PREPARE stmt FROM #qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #did_update = (SELECT ROW_COUNT());
IF #did_update = 0 THEN
SET #qry = CONCAT('INSERT INTO ', usermeta_table, '(user_id, meta_key, meta_value) VALUES (', #temp_id, ', "token_count", ', #token_count, ')');
PREPARE stmt FROM #qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
What I'm after is if the update doesn't update any rows then make a row in the table.
For some reason when I run the above code did_update is always coming back as 0 so the insert aways happens even if the update has updated some rows. How do I fix this to work?
UPDATE: I've just realised that if the values don't change in the update despite the rows existing it returns zero rows. This is what is causing my logic to break...
According to this site,
"you can use ROW_COUNT() with prepared statements, but you need to call it after EXECUTE, not after DEALLOCATE PREPARE, because the row count for allocate prepare is always 0."
I currently am looping through a list of userNames from the DB. as such :
DECLARE
cur1 CURSOR FOR
select user_name
from users
where user_type = 'SP'
and active = 'Y';
OPEN cur1;
read_loop : LOOP
FETCH cur1 INTO userName;
Now for each userName, i am creating tables with data. Obviously, within the above LOOP, i have multiple PREPARE statements like :
set l_table_name = concat("tmp_rec_",userName);
set l_select_cnt = concat("SELECT count(1) into #l_cnt
from information_schema.tables
where table_schema = 'greptlat_db'
and table_name = '", l_table_name, "'");
PREPARE stmt2 FROM #l_select_cnt;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
if l_cnt > 0 then
set droptable = concat("drop table ", l_table_name);
PREPARE stmt1 FROM #droptable;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END IF;
I have more PREPARE statements that build the data that i want and inserts it into the table that i create for each user.
Now because this is in a LOOP, for each user, i have read that PREPARE statements are global. Which means, the above code, "PREPARE stmt1 FROM #droptable", stmt1 will never change even though it gors through the LOOP for each user. Even if i DEALLOCATE it, it still remains for that stored procedure.
How can i reset this stmt1,stmt2,stmt3 ...etc for each time the LOOP starts again ?
Basically l_table_name will change for each time the LOOP goes through, but stmt1 doesnt change.. I need stmt1 to change so that it will use the new l_table_name everytime
Normally a prepare statement deallocated implicitly before the new statement is prepared. So what is the result if you remove DEALLOCATE PREPARE stmt1;. Did you check the '#droptable' value in each loop?