前文:http://www.cnblogs.com/hhelibeb/p/5912330.html
既然后台作业只能在应用服务器运行,那么,我们可以先将要上传的数据保存在应用服务器中,之后再以后台作业的形式导入数据库。这里需要使用的关键字是OPEN DATASET。
1. OPEN DATASET
Syntax
OPEN DATASET dset
FOR { INPUT | OUTPUT | APPENDING | UPDATE }
IN { { BINARY MODE }
| { TEXT MODE ENCODING { DEFAULT
| {UTF-8 [SKIPPING|WITH BYTE-ORDER MARK]}
| NON-UNICODE }
[WITH {NATIVE|SMART|UNIX|WINDOWS} LINEFEED] }
| { LEGACY BINARY MODE [{BIG|LITTLE} ENDIAN]
[CODE PAGE cp] }
| { LEGACY TEXT MODE [{BIG|LITTLE} ENDIAN]
[CODE PAGE cp]
[WITH {NATIVE|SMART|UNIX|WINDOWS} LINEFEED] } }
[AT POSITION pos]
[TYPE attr]
[FILTER opcom]
[MESSAGE msg]
[IGNORING CONVERSION ERRORS]
[REPLACEMENT CHARACTER rc].
效果
打开由dset指定的应用服务器上的文件。
附加项
-
- FOR { INPUT | OUTPUT | APPENDING | UPDATE }
以输入、输出、追加、更新模式打开文件.
- FOR { INPUT | OUTPUT | APPENDING | UPDATE }
-
- IN [LEGACY] { BINARY | TEXT } MODE
以普通的二进制或者文本模式打开文件, 或者以LEGACY二进制或文本模式. LEGACY模式可以指定字节顺序和内码表。在Unicode系统中,LEGACY关键字可能会影响到以东亚文字写入的字段的内容。因此,建议只在没有使用LEGACY附加项的打开的文本中写入内容。
- IN [LEGACY] { BINARY | TEXT } MODE
-
- ENCODING {DEFAULT|UTF-8|NON-UNICODE}
决定了使用何种字符表现形式来操作文件的内容:
DEFAULT - Unicode系统中的UTF-8; 非Unicode系统则不转换.
UTF-8 - UTF-8.
NON-UNICODE -在Unicode系统中,内码表与非Unicode系统文本环境(text evirionment)一致; 非Unicode系统则不转换.
- ENCODING {DEFAULT|UTF-8|NON-UNICODE}
tips: text evirionment
text evirionment是ABAP程序的运行时环境的一部分,由语言、locale和系统内码表组成。同一个内部会话中的所有程序有一个共同的文本环境。默认情况下,内部会话的text environment由登录语言决定,并且也可以被语句set locale指定。当前的text environment包含在系统字段sy-langu中 |
-
- WITH {NATIVE|SMART|UNIX|WINDOWS} LINEFEED
决定文本文件的行尾选项.
- WITH {NATIVE|SMART|UNIX|WINDOWS} LINEFEED
-
- SKIPPING|WITH BYTE-ORDER MARK
控制UTF-8文件中的字节顺序标记(BOM)操作.
- SKIPPING|WITH BYTE-ORDER MARK
-
- {BIG|LITTLE} ENDIAN
决定文件中数值型数据对象被操作的顺序.
- {BIG|LITTLE} ENDIAN
-
- CODE PAGE cp
决定文件中字符型数据对象以指定的内码表cp操作.
- CODE PAGE cp
-
- AT POSITION pos
将文件指针设置到指定的位置pos.
- AT POSITION pos
-
- TYPE attr
为文件设置操作系统参数,或者控制文本文件的行尾选项.
- TYPE attr
-
- FILTER opcom
将一个语句传输给操作系统.
- FILTER opcom
例子:
创建一个文件test.dat。TYPE指定的文件属性是操作系统IBM i5/OS(在OS/400之前)中的。
OPEN DATASET 'test.dat' TYPE 'lrecl=80, blksize=8000, recfm=FB' FOR OUTPUT IN TEXT MODE ENCODING DEFAULT WITH SMART LINEFEED.
-
- MESSAGE msg
如果发生了错误,可以在msg中返回操作系统信息.
- MESSAGE msg
-
- IGNORING CONVERSION ERRORS
如果会话错误发生,该语句可以阻止异常.
- IGNORING CONVERSION ERRORS
-
- REPLACEMENT CHARACTER rc
指定一个字符rc替换无法转换的字符。如果未指定rc,则使用“#”.
- REPLACEMENT CHARACTER rc
使用OPEN DATASET来实现上传数据到应用服务器,即程序中的output_data子进程:
*&---------------------------------------------------------------------* *& Form OUTPUT_DATA *&---------------------------------------------------------------------* * 将数据写入到Applacation Server *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM output_data . DATA s_file TYPE rlgrap-filename. PERFORM generate_filename_in_server USING s_file. OPEN DATASET s_file FOR OUTPUT IN TEXT MODE ENCODING DEFAULT. IF sy-subrc = 0 . LOOP AT itab INTO wa. TRANSFER wa TO s_file. IF sy-subrc <> 0 . MESSAGE 'ERROR!!' TYPE 'E'. ENDIF. ENDLOOP. CLOSE DATASET s_file. WRITE: /'写入服务器文件成功'. PERFORM submit_insert_program USING s_file. "调用导入程序 ELSE. WRITE: /'写入服务器文件失败' . ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form GET_file_name_in_server *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM generate_filename_in_server USING s_file . DATA s_name TYPE string. CALL FUNCTION 'SO_SPLIT_FILE_AND_PATH' EXPORTING full_name = p_source IMPORTING stripped_name = s_name * FILE_PATH = EXCEPTIONS x_error = 1 OTHERS = 2. IF sy-subrc <> 0. * Implement suitable error handling here ENDIF. GET TIME. CONCATENATE '/tmp/' sy-datum sy-uzeit s_name '.txt' INTO s_file. TRANSLATE s_file TO LOWER CASE. ENDFORM.
2,实现导入程序
上传到服务器的程序已经实现,现在新建一个程序ztest_import,实现导入到数据库的功能。同样使用OPEN DATASET语句来实现:
REPORT ztest_import. SELECTION-SCREEN: BEGIN OF BLOCK blk. PARAMETERS: s_file TYPE rlgrap-filename . SELECTION-SCREEN END OF BLOCK blk. DATA: BEGIN OF wa, col1(30) TYPE c, col2(30) TYPE c, col3(30) TYPE c, END OF wa. FIELD-SYMBOLS:TYPE c. TRANSLATE s_file TO LOWER CASE. OPEN DATASET s_file FOR INPUT IN TEXT MODE ENCODING DEFAULT. IF sy-subrc = 0. ASSIGN wa TO CASTING. DO. "由于没有使用MAXIMUM LENGTH选项,所以每次读取的最大字节数 "由 所占字节数决定 READ DATASET s_file INTO. IF sy-subrc = 0. *"ztestly是在SE11中新建的表,结构和上传的excel相符,过程省略 INSERT ztestly FROM wa. ELSE. EXIT. ENDIF. ENDDO. CLOSE DATASET s_file. DELETE DATASET s_file. "成功执行导入后,删除服务器上的文件 ELSE. MESSAGE 'open failed' TYPE 'I
3,在上传程序中调用导入程序
如果你看过我博客中有关submit的文章,可能会记得,submit语句是可以安排程序作为后台作业进行的。下面我们就使用这个特性,在上传程序ztest_upload的子程序submit_insert_program中调用导入程序ztest_import,代码如下:
*&---------------------------------------------------------------------* *& Form SUBMIT_INSERT_PROGRAM *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM submit_insert_program USING s_file. DATA: w_jobid TYPE tbtcjob-jobcount, w_stepnm TYPE tbtcjob-stepcount, p_job_nm TYPE tbtcjob-jobname VALUE 'ZTEST_IMPORT'. CLEAR:w_jobid. CALL FUNCTION 'JOB_OPEN' EXPORTING * DELANFREP = ' ' * JOBGROUP = ' ' jobname = p_job_nm * SDLSTRTDT = NO_DATE * SDLSTRTTM = NO_TIME IMPORTING jobcount = w_jobid EXCEPTIONS cant_create_job = 1 invalid_job_data = 2 jobname_missing = 3 OTHERS = 4. SUBMIT ztest_import WITH s_file = s_file VIA JOB p_job_nm NUMBER w_jobid AND RETURN. IF sy-subrc = 0. CALL FUNCTION 'JOB_CLOSE' EXPORTING jobcount = w_jobid jobname = p_job_nm strtimmed = 'X' EXCEPTIONS cant_start_immediate = 1 invalid_startdate = 2 jobname_missing = 3 job_close_failed = 4 job_nosteps = 5 job_notex = 6 lock_failed = 7 OTHERS = 8. IF sy-subrc <> 0. WRITE: /'后台作业发布失败'. ELSE. WRITE: /'后台作业发布成功'. ENDIF. ENDIF. ENDFORM.
运行zterst_upload,上传一个有效的excel文件,我们便可以在上一篇文章提到的自有作业界面看到后台作业执行成功,并且在SE16中查到自建表zestly中已经插入了相关数据。如果要改变后台作业的计划时间,可以在JOB_CLOSE函数中设置相关参数。