PL/SQL - ORACLE:ORA-01843:不是有效月份

soa*_*soa 1 database oracle toad plsql oracle11g

我想在oracle数据库版本11.2.0.4上的PL/SQL ETL进程内的时间戳列表中插入数据

如果我在Toad中运行"从seletcted行创建INSERT",我将获得以下SQL命令:

 Insert into xxxx$1
   (ID, ITEM, ITEMSIZE, QUALITY, MATERIAL, 
    COLOUR, IMAGEURL, CREATIONDATE, SAMPLEITEMNUMBER, ITEMNUMBER)
 Values
   (111, 339079775, '1', 'Microfaser PRIMABELLE®', 'TEXTILE', 
    '1 (=creme)', 'url', TO_TIMESTAMP('27.06.2016 15:49:35.000000','DD.MM.YYYY HH24:MI:SS.FF'), 'xxx', 'xxxx');
COMMIT;
Run Code Online (Sandbox Code Playgroud)

在PL/SQL中,我生成一个VARCHAR2/String,它看起来像是一样的:

v_sql :=
                                'INSERT INTO xxxx'
                             || p_importpostfix
                             || '  VALUES ('
                             || seq_xxxx.NEXTVAL
                             || ','
                             || v_rec.item_id
                             || ', '''
                             || v_size
                             || ''','''
                             || v_quality
                             || ''','''
                             || v_material
                             || ''','''
                             || v_colour
                             || ''','''
                             || NULL
                             || ''',to_timestamp('''|| to_char( sysdate, 'DD.MM.YYYY HH24:MI:SS')||''',''DD.MM.YYYY HH24:MI:SS.FF''),'''
                             || v_rec.vid
                             || ''','''
                             || v_rec.vid
                             || ''')';
Run Code Online (Sandbox Code Playgroud)

如果我在整个过程之外运行程序奇异,它运行正常.没有错误发生.

如果我运行由数据库JOB启动的完整进程,我将得到一个ORACLE:

ORA-01843:没有有效的月份错误.

我已经阅读了这个问题的另一个帖子而没有理解我的问题.

Luc*_*c M 5

不确定是否是问题,但使用字面上的SYSDATE似乎更容易.

而且似乎你插入了字符串'NULL'.如果要插入NULL值,则不需要使用多个单引号,因为最终字符串不需要单引号来插入NULL值.

v_sql :=
                                'INSERT INTO xxxx'
                             || p_importpostfix
                             || '  VALUES ('
                             || seq_xxxx.NEXTVAL
                             || ','
                             || v_rec.item_id
                             || ', '''
                             || v_size
                             || ''','''
                             || v_quality
                             || ''','''
                             || v_material
                             || ''','''
                             || v_colour
                             || ''','
                             || 'NULL,'
                             || 'SYSDATE,'
                             || ''''
                             || v_rec.vid
                             || ''','''
                             || v_rec.vid
                             || ''')';
Run Code Online (Sandbox Code Playgroud)

编辑

您应该使用参数化查询,而不是尝试构建类似的查询.

    v_sql := 'INSERT INTO xxxx' || p_importpostfix || ' VALUES(:1,:2,:3,:4,:5,:7,:8,:9,:10)';
    v_null := NULL;
    EXECUTE IMMEDIATE v_sql USING IN seq_xxxx.NEXTVAL, 
                                  IN v_rec.item_id, 
                                  IN v_size,
                                  IN v_quality,
                                  IN v_material,
                                  IN v_colour,
                                  IN v_null,
                                  IN SYSTIMESTAMP,
                                  IN v_rec.vid,
                                  IN v_rec.vid;
Run Code Online (Sandbox Code Playgroud)

想象一下,如果你的一个价值包含'......

有关Oracle文档的EXECUTE IMMEDIATE的更多信息.我认为你需要一个Oracle帐户.

  • @soa:这并不妨碍你使用Luc的答案.可以动态设置表名,但这并不意味着你必须连接这些值(这很容易出错).在`execute immediate`调用上绑定参数值是正确的方法. (5认同)
  • @Luc:您不需要Oracle帐户来查看文档. (2认同)