With Oracle table functions, you can define a set of PL/SQL statements in such a way that, when queried, should behave just as a regular query to the table. The table function enables you to manipulate individual collection elements (user-defined object types) in your SQL database code.

However, this may create a database migration challenge because  SQL Server Migration Assistant (SSMA) cannot convert Oracle table functions. Instead, it generates a set of the following errors:

  • O2SS0474: Conversion of the user-defined type variable is not supported and is converted to the VARCHAR(8000) type.
  • O2SS0339: Cannot convert usage of a standalone user-defined type.
  • O2SS0482: Conversion of following TABLE expression is not supported: TABLE().

In this blog post, we will explain why SSMA fails to convert the Oracle table function and give you some tips on how to solve this problem.

The essence of the problem

The example below shows how you can use the table operator to get separate values from the nested table in Oracle.

1
2
3
CREATE OR REPLACE TYPE TEST_FUNCTIONS.TP_OBJECT AS OBJECT (
FIRST_NAME VARCHAR (30),
LAST_NAME VARCHAR (30));

First, you should define the user type TP_OBJECT. Next, you need to define the type TAB_TYPE as a table of a previously defined type.

1
CREATE OR REPLACE TYPE TEST_FUNCTIONS.TAB_TYPE IS TABLE OF TEST_FUNCTIONS.TP_OBJECT;

Continue with running the following SQL statement which uses this table:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DECLARE
p_tab_var TEST_FUNCTIONS.TAB_TYPE;
p_FIRST_NAME VARCHAR(30);
p_LAST_NAME VARCHAR(30);
BEGIN
SELECT TEST_FUNCTIONS.TP_OBJECT (FIRST_NAME, LAST_NAME)
BULK COLLECT INTO p_tab_var
FROM TEST_FUNCTIONS.TAB_FOR_TYPES;
SELECT FIRST_NAME, LAST_NAME
INTO p_FIRST_NAME, p_LAST_NAME
FROM TABLE(p_tab_var)
WHERE FIRST_NAME = 'SAM';
DBMS_OUTPUT.PUT_LINE(p_FIRST_NAME || ' ' || p_LAST_NAME);
END;

During an attempt to convert Oracle statement to SQL Server with SSMA, the following error message appears: «Error O2SS0482: Conversion of following TABLE expression is not supported: TABLE(…).

Possible solutions

There are 3 definite steps that will help you solve this error:

1. Use SSMA to convert the nested tablep_tab_varTEST_FUNCTIONS.TAB_TYPE; to @p_tab_var varchar(8000).

It is important to declare the table variable that has the same structure ast the Oracle object type.

2. SSMA uses the following emulation to convert BULK COLLECT to:

1
2
3
4
5
6
@p_tab_var.AssignData(ssma_oracle.fn_bulk_collect2CollectionSimple(
(
SELECT
FROM
FOR XML PATH )
)

It is important to replace SSMA Extension Pack emulation for BULK COLLECT with a simple INSERT into TABLE variable.  

3. Use SSMA to convert FROM_TABLE p_tab_var) to “FROM AS fci” since it is not possible to convert the TABLE operator.

Ensure replacing the FROM clause with FROM @p_tab_var. 

As a result, you will get the SQL Server code which looks as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BEGIN
DECLARE
@p_tab_var AS TABLE
(FIRST_NAME VARCHAR (30),
LAST_NAME VARCHAR (30))
DECLARE
@p_FIRST_NAME VARCHAR(30),
@p_LAST_NAME VARCHAR(30)
INSERT INTO @p_tab_var
SELECT FIRST_NAME, LAST_NAME
FROM dbo.TAB_FOR_TYPES
SELECT @p_FIRST_NAME = FIRST_NAME, @p_LAST_NAME = LAST_NAME
FROM @p_tab_var
WHERE FIRST_NAME = 'SAM'
PRINT ISNULL(@p_FIRST_NAME, '') + ' ' + ISNULL(@p_LAST_NAME, '')
END
GO

This code will enable you to emulate Oracle’s table function in the database environment of SQL Server.

Final thoughts

Did you find this article useful? Make sure to check our Jumpstart for SSMA offer and find out more about opportunities of applying SSMA for database migration. Also, contact ABCloudz to find out more about we can help you with modernizing your database.

Also, please review our Blog section for the series of blog posts on typical errors of SSMA conversions.

Ready to start the conversation?