Now let’s move on to slightly more realistic (and useful) embedded SQL scenarios and write our first embedded SQL function.
In case you’re wondering, I haven’t forgotten that this series is about SQL, not RPG. However, you’ll see a bit of RPG in this and the next TechTips. My intention is to help you think outside the box and consider using SQL where you normally wouldn’t. In order to do that, this article and the next few articles will provide some examples, using RPG, so that you can get inspired and look at problems the “SQL way.”
You may or may not remember function Rtv_DayOfWeek, from a previous RPG Academy TechTip. I mentioned earlier in this series that there’s an SQL function that performs a similar function: DAYNAME. Let me show you how to use DAYNAME to dramatically simplify the Rtv_DayOfWeek function. I’ll keep the fixed-format procedure interface. Ignore the fixed-format RPG code; it’s not the important part here—I’ll just reuse the parts of the Rtv_DayOfWeek function that remain unchanged.
Just in case you don’t remember or haven’t read that RPG Academy article at all, here’s a quick recap: Rtv_DayOfWeek is used together with Clc_DayOfWeek to retrieve the name of the day of the week. This approach was chosen because the latter function could be used for other purposes, like calculating how long you’d have to work until the weekend, for instance. Now I’m going to change that, because I want my new Rtv_DayOfWeek function to be as simple as possible. The DAYNAME SQL function allows me to merge Clc_DayOfWeek and Rtv_DayOfWeek into one simple, short function. The new function will have Clc_DayOfWeek’s input parameter and a date data type and will produce Rtv_DayOfWeek’s result, a character data type with the name of the day of the week:
* Day of the week (returns the day of the week of a given date in text)*
P Rtv_DayOfWeek B Export
D Rtv_DayOfWeek PI 15A
* Input parameters
D P_Date D VALUE
I declare my work variables, a temporary date, and a character field to return the result to the “outside world”:
* Work variables
D W_Return S 10P INZ(*Blanks)
D W_Date S D INZ
I’ll follow the usual function-creation script and test the input parameter, just like I did in Clc_DayOfWeek, but in free-format:
W_Date = Date(P_Date);
Note that I’m using a Monitor group instead of the TEST operation code, but the idea is the same: I’m checking whether the P_Date input parameter contains a valid date by trying to convert it to a date data type, in this case. If the input date is not valid, I’m returning the ‘NOT_A_DATE’ string. If the input parameter is actually a valid date, I get to the fun part, using an embedded SQL function to replace a bunch of lines of RPG code:
Most of the Clc_DayOfWeek and Rtv_DayOfWeek functions’ code was replaced with this SQL statement. It uses the DAYNAME SQL function to transform the input date, stored in P_Date, into a human-readable day of the week that the SQL function places in the W_Return variable.
SET Instead of SELECT
Note that this can also be performed without a SELECT statement. SQL has a really cool instruction named SET that works like RPG’s EVAL operation code. If I wanted to use SET instead of the whole SELECT statement, I’d write this:
SET :W_Result = DAYNAME(:P_Date);
The rest of the function is trivial:
P Rtv_DayOfWeek E
I’m simply returning the W_Return work variable and ending the function. See how SQL can simplify complex functions? It’s a really powerful tool that you can and should use frequently to solve problems that would otherwise require long and potentially complicated code.
Naturally, there are a few more things I could do here (I have to mention this, otherwise the “no-fixed-format-RPG” people are going to take note and start commenting), such as convert the prototype definition and variable declarations to free-format. That would be the correct thing to do if this were an article about RPG. But it’s not: I’m just using RPG as an example, but I could as well use a C program to do it. It’s just that RPG is easier and (probably) more familiar to most of the readers. Something else I could do would be to replace the whole RPG function with a user-defined SQL function, but that’s something for another article, later in this series.
Next time around, I’ll show another RPG function being completely transformed (and simplified) with a bit of embedded SQL.