使用 db_link 插入获取无效标识符错误

Posted

技术标签:

【中文标题】使用 db_link 插入获取无效标识符错误【英文标题】:Insert using db_link gets invalid identifier error 【发布时间】:2017-11-14 11:02:24 【问题描述】:

我正在构建一个查询,该查询在多个数据库中定位特定记录,并将它们插入到可以访问所有其余部分的主数据库中。

但即使选择运行良好,插入也无法使用甚至不存在的同义词给我一个无效的标识符。

查询:

            INSERT INTO AUDIT_TABLE 

            Select Distinct tr.hmy, trim(tr.uref), tr.stotalamount, tr.upostdate, tr.sdateoccurred
            ,trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) 
            ,trim(v.ucode) 
            ,trim(v.ulastname) 
            ,trim(p.scode) 
            ,trim(p.saddr1) 
            ,trim(b.scode) 
            ,trim(b.sdesc) 
            ,l.icloseday 
            , case when l.icloseday <> 31 then trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) + (l.icloseday - 1 ) else last_day(trunc(tr.sdateoccurred )) end
            , case when l.icloseday <> 31 then 
            case when trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) + l.icloseday <= trunc(tr.sdateoccurred) then add_months((tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1),1)
              else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end
              else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end 
            ,trim(u.uname)
            ,'' 
            from trans@db_link tr
            join detail@db_link d on d.hchkorchg = tr.hmy
            join vendor@db_link v on tr.haccrualacct = v.hmyperson
            join property@db_link p on p.hmy = d.hprop
                 and p.itype = 3
            join bank@db_link b on b.hmy = tr.hperson
            join pmuser@db_link u on u.hmy = tr.husercreatedby
            join lockout@db_link l on l.hprop = p.hmy
            where 
            1=1 
            and tr.itype = 2 
            and tr.manualcheck <> 0 
            and tr.sdatecreated between to_date(trunc(sysdate, 'YEAR')) and to_date(add_months(trunc(sysdate, 'YEAR'), 12)-1)
            and case when l.icloseday <> 31 then 
              case when trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) + l.icloseday <= trunc(tr.sdateoccurred) then add_months((tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1),1)
                else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end
                else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end <> trunc(tr.UPOSTDATE)

错误:

            ORA-00904: "A2"."HUSERCREATEDBY": invalid identifier
            ORA-02063: preceding line from db_link

最奇怪的部分:所有这些数据库都具有相同的架构,但当我遍历所有数据库时,只有其中一些因此错误而失败。

2017 年 11 月 14 日更新:

进一步研究,似乎如果我消除以下两个条件中的任何一个,则 INSERT 没有问题,但我一直在查看它们,不知道为什么引擎会因为这两个而出错简单的 SELECT 没有问题。

and tr.sdatecreated between to_date(trunc(sysdate, 'YEAR')) and to_date(add_months(trunc(sysdate, 'YEAR'), 12)-1)

and case when l.icloseday <> 31 then 
                             case when trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) + l.icloseday <= trunc(tr.sdateoccurred) then add_months((tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1),1)
                             else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end
                           else trunc(tr.sdateoccurred ) - (to_number(to_char(tr.sdateoccurred ,'DD')) - 1) end <> trunc(tr.UPOSTDATE)

【问题讨论】:

似乎缺少授权,您需要将选择访问权限授予其他用户。 但是如果我在没有插入的情况下运行 Select 就没有问题。只有当我想插入“选择”数据时才会出现错误。 是的..所以INSERT 授权丢失了。 是否有特定于来自 db_link 的数据的 INSERT 授权?因为在不使用跨数据库数据的情况下常规插入该表没有问题。仅当我使用另一个数据库中的 SELECT 时,INSERT 才会失败。 【参考方案1】:

仍然不确定为什么会出现此问题,但如果有人也遇到此问题,我通过让 db_link 将远程信息插入远程表中,然后将该信息插入到我的主数据库中的本地表中来解决它.

begin
    sql_update:='DROP TABLE AUDIT_TABLE';
    execute immediate 'begin dbms_utility.exec_ddl_statement@'||v_database_name||'(:sql_update);  end;' using sql_update;

    EXCEPTION
        WHEN OTHERS THEN
          IF SQLCODE = -942 THEN
            NULL; -- suppresses ORA-00942 exception
          ELSE
             RAISE;
          END IF;
END;

sql_update := 'create table AUDIT_TABLE (table structure)';
execute immediate 'begin dbms_utility.exec_ddl_statement@'||v_database_name||'(:sql_update);  end;' using sql_update;
commit;

sql_update := q'[
              INSERT INTO AUDIT_TABLE@#DB_NAME# 
              Select query here
                ]';
execute immediate replace('begin ' || sql_update || ';  end;','#DB_NAME#', v_database_name);
commit;

sql_update := q'[
              INSERT INTO AUDIT_TABLE select * from AUDIT_TABLE@#DB_NAME#
                ]';
execute immediate replace('begin ' || sql_update || ';  end;','#DB_NAME#', v_database_name);
commit;  

【讨论】:

以上是关于使用 db_link 插入获取无效标识符错误的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00904 无效标识符错误

ORACLE ORA-00904: 无效标识符错误

在动态表上获取“ORA00904:无效标识符”

ORA-00904: 插入表时标识符无效

错误报告:SQL 错误:ORA-00904::无效标识符 00904。00000 - “%s:无效标识符”

无法使用外键创建表。错误:ORA-00904: : 无效标识符