Rewriting SQL procedures as SQL user-defined functions
About this task
Procedures and functions share the fact that their routine-bodies are implemented with a compound block that can contain SQL PL. In both, the same SQL PL statements are included within compound blocks bounded by BEGIN and END keywords.
Procedure
- The primary and only reason to do this is to improve routine performance when the logic only queries data.
- In a scalar function you might have to declare variables to hold the return value to get around the fact that you cannot directly assign a value to any output parameter of the function. The output value of a user-defined scalar function is only specified in the RETURN statement for the function.
- If an SQL function is going to modify data, it must be explicitly created using the MODIFIES SQL clause so that is can contain SQL statements that modify data.
Example
CREATE PROCEDURE GetPrice (IN Vendor CHAR(20),
IN Pid INT,
OUT price DECIMAL(10,3))
LANGUAGE SQL
BEGIN
IF Vendor = 'Vendor 1'
THEN SET price = (SELECT ProdPrice FROM V1Table WHERE Id = Pid);
ELSE IF Vendor = 'Vendor 2'
THEN SET price = (SELECT Price FROM V2Table
WHERE Pid = GetPrice.Pid);
END IF;
END
CALL GetPrice( 'Vendor 1', 9456, ?)
CREATE FUNCTION GetPrice (Vendor CHAR(20), Pid INT)
RETURNS DECIMAL(10,3)
LANGUAGE SQL MODIFIES SQL
BEGIN
DECLARE price DECIMAL(10,3);
IF Vendor = 'Vendor 1'
THEN SET price = (SELECT ProdPrice FROM V1Table WHERE Id = Pid);
ELSE IF Vendor = 'Vendor 2'
THEN SET price = (SELECT Price FROM V2Table
WHERE Pid = GetPrice.Pid);
END IF;
RETURN price;
END
This function takes in two input parameters and returns a single scalar value, conditionally based on the input parameter values. It requires the declaration and use of a local variable named price to hold the value to be returned until the function returns whereas the SQL procedure can use the output parameter as a variable. Functionally these two routines are performing the same logic.
Now, of course the execution interface for each of these routines is different. Instead of simply calling the SQL procedure with the CALL statement, the SQL function must be invoked within an SQL statement where an expression is allowed. In most cases this isn't a problem and might actually be beneficial if the intention is to immediately operate on the data returned by the routine. Here are two examples of how the SQL function can be invoked.
VALUES (GetPrice('Vendor 1', 9456))
SELECT VName FROM Vendors WHERE GetPrice(Vname, Pid) < 10