I will make simpler than it is to get the answer I need without make you read a lot of code.
MySQL stored procedure:
CREATE PROCEDURE add_player
(IN name varchar(100),
IN isTrue boolean)
BEGIN
START TRANSACTION;
insert into tags (name,is_player) values (name,isTrue);
COMMIT;
END //
player_controller.rb
ActiveRecord::Base.connection.execute("call add_player('#{name}', #{is_player})")
Two problems I see(if you see more - say):
if name contains ' it breaks the call
sql injection - I don't use ? as parameters when I call the stored procedure. The reason is that it's just not working when I'm try with ?. I tried also change it to Player.where("add_player(?,?)",name,is_player)
Did you try something like this ?
ActiveRecord::Base.connection.execute("call add_player(#{ActiveRecord::Base.sanitize(name)}, #{is_player})")
There is another way suggested on the following SO link
using sanitize_sql_array to escape strings
The only problem is that sanitize_sql_array is not a public method
Related
I'm painfully new to SQL/mySQL as a whole so I'm flying blind right now so apologies.
I made a procedure in mySQL that selects a varchar data from a specific column and table, turn it into INT (contents of said column are numerical to begin with) and output its values after going through a mathematical operation as a (very simple) attempt in data masking. As follows:
CREATE PROCEDURE qdwh.mask_varchar_num2(tablename varchar(100), colname varchar (100))
BEGIN
set #a=concat('select','(','(','(','(','select',colname ,'from',tablename,')','+','0',')','+','297',')','*','5',')','as','colname');
prepare query from #a;
execute query;
deallocate prepare query;
END
but when i tried to call the procedure with the following line:
select [column] , mask_varchar_num2 ([column]) from [table];
an error "FUNCTION qdwh.mask_varchar_num2 does not exist" shows up. I wanted the script to output a select function of the column in question after the conversion to INT and the mathematical operation done to it, so i can then use this procedure in a larger script ("create table select as" kinda stuff) to convert the whole table into masked data as needed.
Is there something i am missing and what am i doing wrong? Dbeaver acknowledges the procedure script as legit so i dont know whats wrong. Thanks in advance for the advice.
Procedures are run by using call and cannot be called within a select query. To define a function, you need to use create function.
not an answer but here's what your select looks like..
set #colname='a';
set #tablename='t';
set #a=concat('select','(','(','(','(','select',#colname ,'from',#tablename,')','+','0',')','+','297',')','*','5',')','as','colname');
select #a
'select((((selectafromt)+0)+297)*5)ascolname'
missing a lot of spaces between tokens
I have a nested MySQL stored procedure that's basically structured like this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_main`(in param1 int, in param2 int)
BEGIN
declare refid int;
# do some stuff here
select refid;
call sp_child(param1, param2, refid);
END
Both sp_main and sp_child are stored procedures, the problem is sp_child itself has a return value (call it refid2) and when I use sqlquery in RODBC I always ended up getting refid2 instead of refid (which is what I need), although when I run it in MySQL Workbench I ended up seeing both refid and refid2 when call sp_main(...). All sp_child param are "in" params and the only "out" value is returned in the end of sp_child call.
Is there any way I could either:
Change the code in sp_main so that the output in sp_child is does not gets shown? I tried to use set #output = call sp_child(...); to suppress the output showing up when calling sp_main but that ended up giving me a syntax error. The sp_child unfortunately can not be modified as it is shared with several other SPs and changing the params would require changing all of the dependent SPs. Also obviously making sp_child to become a function is also out of question.
OR
Somehow use sqlquery in RODBC (or another R package or function) to somehow get both the output from the sp_child call AND sp_main call?
Thanks!
I have a Stored Procedure wrote in SQL Server that I need to convert to MySQL, which has this code inside.
SQL server code
declare #resultatSP table (...);
...
insert into #resultatSP execute other_procedure(...);
...
My problem is that in SQL Server, the "result" of the last select done in the SP other_procedure is stored in #resultatSP. (I don't know if it is conventional but it works), but I cannot reproduce it in MySQL.
I tried things like this:
MySQL code
drop temporary table if exists resultatSP;
create temporary table resultatSP (...);
...
resultatSP = CALL other_procedure(...);
OR
CALL other_procedure INSERT INTO resultatSP;
But nothing works.
I read that in MySQL, call stored procedure does not return result and we must use OUT/INOUT parameters. But I cannot change the other_procedure(...).
What is the most confusing is that this other_procedure has been convert in MySQL and it is used in java with some Javax.persistance annotations as #NamedNativeQuery or #SqlResultSetMapping and these annoations succeed to get the "result" of the last select of the stored procedure other_procedure(...) converted in MySQL. I don't know how these annotations make it.
In a sql script that does sequential execution, is there a way one can introduce an IF THEN ELSE conditional to control the flow of query execution?
I happened to run into this http://www.bennadel.com/blog/1340-MySQL-Does-Not-Support-IF-ELSE-Statements-In-General-SQL-Work-Flow.htm
which says that the IF THEN ELSE will not work in a sql script.
Is there another way around?
Basically, I want to run a particular "select colName from table" command and check if colName corresponds to a particular value. If it does, proceed with the rest of the script. Else, halt execution.
Please advise.
I just wrap my SQL script in a procedure, where conditional code is allowed. If you'd rather not leave the statements lying around, you can drop the procedure when you're done. Here's an example:
delimiter //
create procedure insert_games()
begin
set #platform_id := (select id from platform where name = 'Nintendo DS');
-- Only insert rows if the platform was found
if #platform_id is not null then
insert into game(name, platform_id) values('New Super Mario Bros', #platform_id);
insert into game(name, platform_id) values('Mario Kart DS', #platform_id);
end if;
end;
//
delimiter ;
-- Execute the procedure
call insert_games();
-- Drop the procedure
drop procedure insert_games;
If you haven't used procedures, the "delimiter" keyword might need some explanation. The first line switches the delimiter to "//" so that we can include semi-colons in our procedure definition without MySQL attempting to interpret them yet. Once the procedure has been created, we switch the delimiter back to ";" so we can execute statements as usual.
After doing some research I think I may have found a way to work around this. I was looking for a way to verify if a script had already executed against a target database. This will be primarily for version control of my databases. I have a table created to keep track of the scripts that have been executed and wanted some flow inside my scripts to check that table first before execution. While I have not completely solved the problem yet I have created a simple script that basically does what I need, I just need to wrap the DDL into the selects based on the value of the variables.
step 1 - Setup a bit variable to hold the result
step 2 - do your select and set the variable if the result is found
step 3 - Do what you need to do on false result
step 4 - Do what you need to do on true result
Here is the example script
set #schemachangeid = 0;
select #schemachangeid := 1 from SchemaChangeLog where scriptname = '1_create_tables.sql';
select 'scriptalreadyran' from dual where #schemachangeid = 1;
select 'scriptnotran' from dual where #schemachangeid = 0;
I also recognize this is an old thread but maybe this will help someone out there trying to do this kind of thing outside of a stored procedure like me.
I am writing some MySQL procedures for a web-based application, and something that strikes me is that there is no argument's type check at all.
For instance, if I have the following :
CREATE PROCEDURE foo(n CHAR(4))
I can call it with whatever I want, it will accept it and only take the four first characters. But if I want to do something like this :
use base;
DELIMITER $$
DROP PROCEDURE IF EXISTS open $$
CREATE PROCEDURE open(n INT)
BEGIN
SELECT * FROM prod_charts LIMIT n;
END $$
DELIMITER ;
It will just crash when called with a non-int parameter. And there is no feedback : when called from php, I just get nothing, and when I try it in phpMyAdmin, I am sent back to the home's page.
So my question is : how can I make it a little bit safer ? is there a way to check a variable's type in those procedures ?
Unfortunately, I don't know of a way of doing this directly in mySQL. In other RDMS - like MS SQL, there are functions like isNumeric() that you can use.
Create the following function in mySQL and use it to check to see if the value passed in is numberic.
CREATE FUNCTION ISNUMERIC(myVal VARCHAR(1024))
RETURNS TINYINT(1) DETERMINISTIC
RETURN myVal REGEXP '^(-|\\+)?([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
That should cover most (if not all) possibilities.