Argument's type in MySQL procedures? - mysql

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.

Related

How To emulate MySQL Function with OUT parameter

As far as I understand MySQL does not support functions with OUT (as well as IN / INOUT) parameter types.
I am creating a function
DROP FUNCTION IF EXISTS `GETGOSTAUTHRUS`;
CREATE DEFINER = `root`#`localhost` FUNCTION `GETGOSTAUTHRUS`(`PublID` int)
RETURNS varchar(1024) CHARSET utf8
BEGIN
RETURN .....;
END;
This function is called from SELECT statement:
SELECT
GETGOSTAUTHRUS(p.ID) `AuthList`,.......
FROM....
Everything works fine. However I need to extend the function and return another value of varchar type but I can not declare out prefix varchar(50) variable in the same way as I do in procedure declaration:
CREATE procedure `GETGOSTAUTHRUS`(PublID int, OUT prefix varchar(50))
BEGIN
The only way out I have invented is to declare another function and call it separately, but it seems not optimal as the second function will fetch and process the same data from the tables.
How can I manage the issue?
Functions are supposed to return only one value, you might have the wrong approach here. We don't know what you're exactly trying to do, so we can't tell if we're dealing with a XY problem here. There may be better solutions to your overall problem.
You can solve this however with user-defined variables. These are session bound, so make sure to reset them in your function.

Safe way to send parameters to stored procedure in ROR

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

IllegalArgumentException: Type cannot be null (in JAVA)

I'm facing the exact issue as described in this SO link which hasn't been answered. I've tried the suggestions given in the comment section, nothing works.
I've searched online for the answers and found no luck.
My Procedure looks like this.
DROP PROCEDURE IF EXISTS userdb.new_test;
CREATE PROCEDURE userdb.new_test (IN arg varchar(255))
BEGIN
select * FROM message
END;
and from this link I got to know
This exception indicates that a method is called with incorrect input arguments. Then, the only thing you must do is correct the values of the input parameters. In order to achieve that, follow the call stack found in the stack trace and check which method produced the invalid argument.
does anyone know how to fix this?
That's most probably because of the non-default value parameter in your procedure IN arg varchar(255) and if not wrong you are probably calling the procedure without passing any parameter. You need to call like
call userdb.new_test 'some value'
MySQL doesn't support parameter default value likewise in SQL Server and so you can't say IN arg varchar(255) = null
Also, I don't see you are using that parameter in your query and so best is drop it;
DROP PROCEDURE IF EXISTS userdb.new_test;
CREATE PROCEDURE userdb.new_test
BEGIN
select * FROM message
END;

Entity Framework stored procedure: Function Import to Complex Type, Error on Get Column Information

I am working on a project in VS2012 while using MySQL database and Entity Framework 5.0.0.
When I try to create a new Complex type from a stored procedure, I get an error when clicking "Get Column Information" button:
The selected stored procedure or function returns no columns.
My stored procedure code is as following:
DROP PROCEDURE IF EXISTS SearchAlgemeenSet;
Delimiter //
CREATE PROCEDURE SearchAlgemeenSet(IN in_searchQuery VARCHAR(255))
BEGIN
SELECT Blokken, Jaargang, Werk_Uren
FROM algemeensets
WHERE Blokken LIKE in_searchQuery
OR Jaargang LIKE in_searchQuery
OR Werk_Uren LIKE in_searchQuery;
END
//
Delimiter ;
I'm positive that it returns columns if the in_searchQuery parameter has a match.
In my research, I have found plenty solutions for Microsoft SQL database. But none of those solutions apply to MySQL database.
How to solve this?
I'm positive that it returns columns, if the in_searchQuery
parameter has a match.
Because you are not using any wild card for partial search, unless it finds an exact match, for in_searchQuery value, no rows will be returned. For partial match to happen, you need to use wild card symbol '%' with the in_searchQuery value.
Modified procedure, should be like the following:
DROP PROCEDURE IF EXISTS SearchAlgemeenSet;
Delimiter //
CREATE PROCEDURE SearchAlgemeenSet(IN in_searchQuery VARCHAR(255))
BEGIN
set #search_criteria := concat( '%', in_searchQuery, '%' );
SELECT Blokken, Jaargang, Werk_Uren
FROM algemeensets
WHERE Blokken LIKE #search_criteria
OR Jaargang LIKE #search_criteria
OR Werk_Uren LIKE #search_criteria;
END;
//
Delimiter ;
When no search criteria has any matches found, and empty set would be returned.
In your scripting language, you have to check, in advance, whether the procedure has returned any results or not. Based on that, you can show a message that no data found or you can perform other actions.

Suppose I want to create a "stored function" for MYSQL. Where do I wrote it? Which file?

Of course, I could go into mysql console and type the Function. But what if I want to store it for future use? What do I do?
Most projects have an SQL file to initialize the database from scratch. This way, one can set up the application database by simply running this SQL file. Your CREATE PROCEDURE/FUNCTION query would also go in this file.
There's a good tutorial here:
http://www.databasejournal.com/features/mysql/article.php/3525581/MySQL-Stored-Procedures-Part-1.htm
You need to use stored procedures. Once written, these are stored in the database along with your tables. They can be invoked using the CALL <procedure> statement.
Here's an example procedure that populates table1 with random values:
DELIMITER //
DROP PROCEDURE IF EXISTS autofill//
CREATE PROCEDURE autofill()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 20000 DO
INSERT INTO table1 (size) VALUES (FLOOR((RAND() * 1000)));
SET i = i + 1;
END WHILE;
END;
//
DELIMITER ;
Once the procedure has been written, it is called like this:
CALL autofill();