原创 无峰 [ ABAP 技巧与实战 ](javascript:void\(0\);)
一
前言
最近项目上使用SLT(SAP Landscape Transformation,是一个实时数据复制工具,主要用于将数据从源系统(如SAP
ERP或非SAP系统)复制到目标系统)把SAP数据同步到ORACLE数据库. 碰到日期,时间戳相关字段的问题,尝试了一些解决方法.
** 本文主要介绍SLT同时日期,时间戳的相关注意事项 **
**
**
> SLT的配置
>
> 无峰,公众号:ABAP 技巧与实战 [ SAP操作手册之 LT数据同步配置
> ](https://mp.weixin.qq.com/s/mYja0Ps5zttkPIm0e9jZJQ)
二
类型定义
** 日期 **
SAP中的日期类型 DATS
ORACLE中的日期类型DATE
** 时间戳 **
• CHAR14 (日期&时间 YYYYMMDDHHMMSS),早期代码及自定义代码常用
• DEC15.0 数字型, 本质也是 YYYYMMDDHHMMSS转换成数字(常见域名: TZNTSTMPS )
• DEC21.7 数字型. 本质是YYYYMMDDHHMMSS + 毫秒 转换成数字(常见域名TZNTSTMPL) ,示例: EKKO- LASTCHANGEDATETIME
ORACLE中的时间戳
常用 TIMESTAMP
如下图, 给出了同一个表在SAP及ORACLE中的字段定义, 其中SAP中的时间戳使用了CHAR定义
三
类型转换
SLT支持类型转换, 可以定义全局或指定表的类型转换
事务代码 LTRS
全局类型映射(不推荐, 全局类型可能导致表创建失败)
指定表的类型隐射
• 基于类型
• 基于表字段
四
日期写入报错处理
ORA-01843 无效的月份
或者其它相关的错误
_** 01 ** _
** 错误分析 **
SAP日期,时间戳本质可以理解为字符串. ORACLE字符串写入日期需要指定日期格式,日期语言等信息
可以在SQL语句中用TO_DATE 或 TO_TIMESTAMP 等函数在语句中把字符串转换成日期或时间戳.
但是因为SLT不支持把字段内容转换成带有函数的字符串
比如 '20240101' -> TO_DATE( '20240101' ,'YYYY-MM-DD') 以便符合ORACLE参数定义的日期格式
ORACLE数据库也支持隐式的字符串转换成日期,但是字符串必须符合数据库参数定义的日期格式.
_** 02 ** _
** 数据库参数 **
查看数据库日期格式及语言的语句
SELECT *FROM nls_session_parameters
WHERE parameter LIKE '%TIME%' OR parameter LIKE '%LANG%' OR parameter LIKE
'%DATE%';
_** 03 ** _
** 调整参数值 **
数据库参数可以全局指定, 也可以在会话中指定.
如果数据库管理员不允许修改全局参数(可能影响数据库中的其它SCHEMA). 就只能在连接数据库时,或连接数据库后通过修改会话参数指定
如下语句用于会话级调整日期,时间戳相关参数值
ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';
ALTER SESSION SET NLS_TIME_FORMAT = 'HH24:MI:SS.FF';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF TZR';
_** 04 ** _
** SLT连接参数 **
SLT没有提供相关的连接参数, 也没有提供连接后执行SQL命令的配置
SLT允许的连接参数如下图
_** 05 ** _
** 基于用户的参数设置 **
因此考虑ORACLE数据库是否存在用户级别的参数设置.(有了这个思路后, 通过和AI交互,获取了如下方式)
通过设置用户登录触发器,来调整会话参数. 实测通过
CREATE OR REPLACE TRIGGER slt_set_date_format
AFTER LOGON ON DATABASE
BEGIN
IF USER = 'MDGMIDUAT' THENEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = ''YYYYMMDD''';
END IF;IF USER = 'MDGMIDUAT' THENEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_LANGUAGE = ''AMERICAN''';
END IF;IF USER = 'MDGMIDUAT' THENEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT =
''YYYYMMDDHH24MISS''';
END IF;IF USER = 'MDGMIDUAT' THENEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TIME_FORMAT = ''HH24MISS''';
END IF;IF USER = 'MDGMIDUAT' THENEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT =
''YYYYMMDDHH24MISS''';
END IF;END;SLT连接数据库后,触发这个触发器,把语言,日期格式调整为SAP相同的样式. 这样日期,时间戳写入ORACLE数据库就不会出错了.
五
另一个解决办法
因为ORACLE数据库支持隐式字符串转换成日期.
因此可以考虑在SAP段把日期,时间戳内容转换成数据库当前参数允许的内容
比如
数据库参数的日期格式 DD-MON-YY
把日期执行下面的转换
20220101 -> 01-JAN-22
这样也可以写入到数据库中. 但是这样会涉及到所有日期相关字段类型和内容调整
六
总结
SLT把带有日期的SAP表写入ORACLE数据库,需要执行如下处理
• 类型转换
• ORACLE数据库设置用户级别的参数值(通过登录触发器实现)
** THE **
** END **
** 约定 **
如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.
syjf1976
sharry_xlp
Yannick_Duan
申请进入公众号讨论群提问或者参与话题讨论