I have a function that is defined as:
Where XXXXX is my schema YYYYY is my package.
PROCEDURE "XXXXX"."YYYYY.SPATIAL::SP_GA_PT_PATH_DISTANCE" (IN PID NVarChar(36))
LANGUAGE SQLScript
SQL SECURITY INVOKER
--DEFAULT SCHEMA <default_schema_name>
AS
BEGIN
I want to call a function and assign the result to a variable, I have tried the following two ways:
intIntersect := XXXXX.YYYYY.SPATIAL::GA_INTERSECT (32.925148, -117.020051,
32.924672, -117.019454,
32.924488, -117.020322,
32.924849, -117.019759);
SELECT XXXXX.YYYYY.SPATIAL::GA_INTERSECT (32.925148, -117.020051,
32.924672, -117.019454,
32.924488, -117.020322,
32.924849, -117.019759) INTO intIntersect FROM DUMMY;
I have played with different permutations of this, but nothing works.
Any ideas?
Thanks.
What you describe as a FUNCTION is really a PROCEDURE in your code example.
These differ in the ways you can call either of them.
Procedures need to be called via the CALL statement.
Functions can either be used as scalar function in all places where you can use expressions (i.e. the projection list of a SELECT-statement) or, for table-typed functions, like a table in the WHERE condition.
The parameters handed over to the procedure seem to be a list of data items.
The general way to pass "lists" of parameters is to use a table-type parameter:
CREATE FUNCTION "XXXXX"."YYYYY.SPATIAL::SP_GA_PT_PATH_DISTANCE"
(IN_PIDS TABLE (PID NVARCHAR(36)) )
RETURNS TABLE (DISTANCES DECIMAL)
AS
BEGIN
SELECT * FROM :IN_PIDS;
...
Related
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 am trying to create a stored procedure in MySQL which is not supposed to be vulnerable to SQL injection. Hence I am using prepared statements inside this. I have a Patient table to which I want to add data using this procedure. This is what my stored procedure looks like.
DROP PROCEDURE IF EXISTS CreatePatient;
DELIMITER ##
CREATE PROCEDURE CreatePatient (IN alias VARCHAR(20))
BEGIN
PREPARE q1 FROM 'insert into Patient values (?)';
set #alias = alias;
EXECUTE q1 USING #alias;
END ##
DELIMITER ;
When I tried to run this without setting a new variable #alias,
EXECUTE q1 USING alias;
I am getting an SQL syntax error. From my understanding, it doesn't seem right to create a variable within the method body just to assign it the input variable to the procedure. What am I missing here?
Mysql has 3 types of variables
User Defined Variables
Local variables
session variables
User defined variables have session scope while local variables have a block scope i.e within BEGIN-END Block.
Because local variables are in scope only during stored program execution, references to them are not permitted in prepared statements created within a stored program. Prepared statement scope is the current session, not the stored program, so the statement could be executed after the program ends, at which point the variables would no longer be in scope. For example, SELECT ... INTO local_var cannot be used as a prepared statement. This restriction also applies to stored procedure and function parameters
See official docs
Here's the start of my typical stored procedure:
CREATE DEFINER=`joe`#`%` PROCEDURE `Add_Item`(
IN usernameApp VARCHAR(255),
IN barcodeApp VARCHAR(255),
IN quantityApp VARCHAR(255)
)
BEGIN
I would call it with something like this code from PHP:
CALL Add_Item('ethan', '987261826671', '12');
The issue is that I am looking for something a bit more dynamic, where I can call the stored procedure with parameters in any order (because I can't guarantee the order in my dynamic app I'm trying to create). I feel like named parameters would work, but I know MySQL doesn't have that for procedures.
Something like this would work, for example (pseudo code obviously):
CALL Add_Item(quantity>'12' name>'ethan', barcode>'987261826671');
Ideas?
Using PDO:
$sth = $dbh->prepare('CALL Add_Item(:quantity, :name, :barcode)');
// You can pass paremeters in any order here:
$sth->execute([
':quantity' => 12,
':name' => 'ethan',
':barcode' => '987261826671',
]);
The arguments to a stored proc are fixed. There are no optional arguments and the order is fixed. There's no such thing as named arguments like in Perl or Python.
A workaround you could do is the following:
SET #quantity = 12;
SET #name = 'ethan';
SET #barcode = '987261826671';
CALL Add_Item();
In other words, use session variables instead of procedure arguments. Then you can set the session variables in any order you want.
Session variables can be referenced within procedure code simply by using the # prefix. Session variables are visible only within the current session.
But this workaround doesn't work well for recursive procedures, where you want to pass parameters to the procedure in recursive calls.
Also, if you call the procedure multiple times during your session, you'd have to remember to change the values or else the values from prior calls could carry over to subsequent calls.
I have to say this is an odd question. Many programming languages, even PHP, require you to call a function or procedure with arguments in a specific order. This isn't too difficult a constraint.
Situation: Having a SQL procedure which "returns" result via "SELECT x" statements. For some reasons it is not allowed to change it to a function or changing that procedure in any way. How can I obtain the result like:
set #result = 0;
#result = call SomeProcedure(#p1, #p2);
But since it is a procedure not a function above code won't compile/work. How can I achieve that in MySQL. In C++ it works but in MySQL I found no way ...
It is not possible.
Result sets returned from select ... will always be returned to the caller of the first procedure, even if you make several levels of sub calls.
Functions return a value (but not a result set) that you can use inside other procedures or functions.
Your only option is to either set session variables or to store the result in a temporary table that the calling procedure knows about.
I tried finding an answer to this online, but could not find any clear explanation:
Does the # in a stored procedure serve some sort of special purpose/signify something in particular? I am a little confused as to when we use it, since examples seem to vary on its usage.
For instance in the following example # is used:
DELIMITER $
DROP PROCEDURE IF EXISTS emp_count_2;
CREATE PROCEDURE emp_count_2(OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM Employee;
END
$
DELIMITER ;
/* To invoke this procedure use the mysql command statement
CALL emp_count_2(#empCount);
SELECT #empCount;
*/
Once again, does the # in this example serve some sort of special purpose, or can we remove the # and just use normal variable names?
**EDIT: I am using MySql
The #variable syntax in MySQL denotes a user-defined session variable. You can set these user variables outside a stored procedure, but you can also set them inside a stored procedure, and the effect is that the variable retains the value after your procedure call returns.
So in your example, the following would also do the same thing:
CREATE PROCEDURE emp_count_2()
BEGIN
SELECT COUNT(*) INTO #empCount FROM Employee;
END
CALL emp_count_2(); /* sets #empCount as a side-effect */
SELECT #empCount;
It's okay for multiple sessions to set the user variable in this way concurrently, because user variables are scoped to a single session, and concurrent sessions may have variables of the same name, but with different values.
The variable syntax with no # prefix is for variables local to the procedure, either procedure parameters, or else local variables declared with DECLARE within the procedure body.
This usage you have, passing a user variable as a parameter and assigning it in the body of the procedure, is useful if you want to call a procedure several times and store the result in separate user variables. Otherwise each call to the procedure would overwrite the previous value in the #empCount user variable for the current session.