Procedures/Functions with ROWTYPE Parameters Defaulted to NULL
The %ROWTYPE attribute in Oracle defines the particular record type of a row in a table. A common usage of %ROWTYPE attribute is to have variables declared as ROWTYPE of a table to transfer data in and out of a procedure or function. An IN ROWTYPE parameter of a function or procedure can be set with a default value. Often, the IN ROWTYPE parameter is defaulted to NULL. For example,
PROCEDURE proc_foo_rowtype(
row_a employees%ROWTYPE DEFAULT NULL )
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('ID = ' || NVL(TO_CHAR(row_a.employeeID), 'NULL'));
DBMS_OUTPUT.PUT_LINE('NAME = ' || NVL(TO_CHAR(row_a.firstName), 'NULL'));
END proc_foo_rowtype;
Given the example above, employee table has two rows: employeeID and firstName. When the convert record as a list of separated variables (found under Record conversion in Project Settings for SSMA for Oracle) is set to Yes, SSMA will create separate parameters for each row of the employees table.
PROCEDURE dbo.PROC_FOO_ROWTYPE
@row_a$EMPLOYEEID float(53) = NULL,
@row_a$FIRSTNAME nvarchar(max) = NULL
AS
BEGIN
PRINT 'ID = ' + isnull(CAST(@row_a$EMPLOYEEID AS varchar(max)), 'NULL')
PRINT 'NAME = ' + isnull(CAST(@row_a$FIRSTNAME AS varchar(max)), 'NULL')
END
Note that when the ROWTYPE parameter is defaulted to NULL, SSMA will also have the converted parameters default to NULL as shown above.
Now, let’s have a little fun by having a ROWTYPE parameter in a nested procedure. Here’s an example:
PROCEDURE PROC_FOO_OUTER
IS
empRow employees%ROWTYPE;
procedure proc_foo_inner(
row_a IN employees%ROWTYPE default null)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(‘First name = ' || NVL(TO_CHAR(row_a.FirstName), 'NULL'));
DBMS_OUTPUT.PUT_LINE(‘Last Name = ' || NVL(TO_CHAR(row_a.LastName), 'NULL'));
END proc_foo_inner;
BEGIN
empRow.LastName := 'Smith';
empRow.FirstName := 'John';
proc_foo_inner();
proc_foo_inner(empRow);
END PROC_FOO_OUTER;
This example is quite straightforward. Let’s assume there is an employee table with FirstName and LastName columns of nvarchar2(20) and nvarchar2(40) respectively. The executing this procedure in Oracle would the following result:
First name = NULL
Last name = NULL
First name = John
Last name = Smith
Now, let’s convert this procedure to SQL Server 2012 using SSMA for Oracle. We will set the following settings in SSMA as such
- · local modules conversion is set to Inline
- · convert record as a list of separated variables set to Yes
The first setting is to convert the inner procedure into nested block Begin..End. The second setting will create separate variables for FirstName and LastName.
Below is the result of the conversion. There are two nested blocks corresponding to the respective inner procedures. Each nested block contains its own variables for LastName and FirstName. For the block representing proc_foo_inner(), the two variables are set to NULL. For the block representing proc_foo_inner(empRow), the variables are set to the proper empRow values.
PROCEDURE dbo.PROC_FOO_OUTER
AS
BEGIN
DECLARE
@empRow$LASTNAME nvarchar(40),
@empRow$FIRSTNAME nvarchar(20),
SET @empRow$LASTNAME = 'Smith'
SET @empRow$FIRSTNAME = 'John'
BEGIN /* proc_foo_inner() */
DECLARE
@proc_foo_inner$row_a$LASTNAME nvarchar(max)
DECLARE
@proc_foo_inner$row_a$FIRSTNAME nvarchar(max)
SET @proc_foo_inner$row_a$LASTNAME = NULL
SET @proc_foo_inner$row_a$FIRSTNAME = NULL
BEGIN
PRINT 'Last name = ' + isnull(CAST(@proc_foo_inner$row_a$FIRSTNAME AS varchar(max)), 'NULL')
PRINT 'First Name = ' + isnull(CAST(@proc_foo_inner$row_a$LASTNAME AS varchar(max)), 'NULL')
END
END
BEGIN /* proc_foo_inner(empRow) */
DECLARE
@proc_foo_inner$row_a$LASTNAME$2 nvarchar(max)
DECLARE
@proc_foo_inner$row_a$FIRSTNAME$2 nvarchar(max)
SET @proc_foo_inner$row_a$LASTNAME$2 = @empRow$LASTNAME
SET @proc_foo_inner$row_a$FIRSTNAME$2 = @empRow$FIRSTNAME
BEGIN
PRINT 'Last name = ' + isnull(CAST(@proc_foo_inner$row_a$FIRSTNAME$2 AS varchar(max)), 'NULL')
PRINT 'First Name = ' + isnull(CAST(@proc_foo_inner$row_a$LASTNAME$2 AS varchar(max)), 'NULL')
END
END
END