Migrating Oracle to SQL Server using SSMA–Error O2SS0041 Illegal Identifier
When converting Oracle schema to SQL Server using SSMA, you may encounter an error when your table contains a DATE column with default value. This blog post describes the reason for the error and what you should do when you encounter this error.
Consider the following example
-- Oracle source table:
CREATE TABLE TEST.T1
(
COL1 DATE DEFAULT to_date('01/02/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
COL2 DATE DEFAULT sysdate
);
-- Converted table using SSMA:
CREATE TABLE
[dbo].[t1]
(
/*
* SSMA error messages:
* O2SS0041: Identifier 'sysdb.ssma_oracle.to_date2('01/02/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS')' cannot be prefixed with a database name in this context.
*/
[COL1] datetime2(0) NULL,
[COL2] datetime2(0) DEFAULT sysdatetime() NULL
)
SSMA converts Oracle’s to_date function with an emulator function (stored in SYSDB database when you install SQL Server Migration Assistant Extension Pack): sysdb.ssma_oracle.to_date.
The emulation function is used to ensure the date is stored according to the specified format. For example:
-- Oracle original statement
SELECT to_date('01/02/2010 00:00:00', 'DD/MM/YYYY HH24:MI:SS') FROM DUAL;
-- converting using SQL’s CAST statement will result in the following (using default SQL_Latin1_General_CP1_CI_AS collation)
SELECT CAST('01/02/2010 00:00:00' as datetime)
-- result: 2010-01-02 00:00:00.000 (January 2, 2010)
-- converting using SSMA emulator will result in the same value with Oracle (regardless database collation setting)
SELECT sysdb.ssma_oracle.to_date2('01/02/2100 00:00:00', 'DD/MM/YYYY HH24:MI:SS')
-- result: 2100-02-01 00:00:00.0000000 (February 1, 2010)
However, when to_date is used as default value in the table definition, the expression refers to the emulator function in a separate database – which is not permitted in SQL Server:
USE test2
GO
CREATE FUNCTION dbo.fn_const(@const INT) RETURNS INT
AS
BEGIN
RETURN @const
END
GO
USE test
go
CREATE FUNCTION dbo.fn_const(@const INT) RETURNS INT
AS
BEGIN
RETURN @const
END
Go
CREATE TABLE tbl1 (Col1 INT DEFAULT dbo.fn_const(1))
-- successfully created
CREATE TABLE tbl2 (col1 INT DEFAULT test2.dbo.fn_const(1))
/*
Msg 128, Level 15, State 1, Line 1
The name "test2" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
*/
When you encounter the SSMA error, you can proceed with the conversion and add the default value post conversion:
ALTER TABLE [dbo].[t1] ADD DEFAULT CAST('02/01/2010 00:00:00' AS DATETIME2) FOR [COL1]
Note that you have to make sure to set the default value with string format consistent with your collation setting.