UPSERT进入具有动态表名的表

任何更好的UPSERT进入表的方法,提供:

  • 数据以~1行/秒进行upsert
  • 表名是DYNAMIC,使用传递给它的ObjectID参数生成

以下程序:“ORA-00942:表格或视图不存在”

CREATE OR REPLACE PROCEDURE PROCEDURE "SPINSERTDATA" ( pObjectID IN RAW, pDateTime IN TIMESTAMP, pValue IN BINARY_DOUBLE, ) AS BEGIN Declare vQueryInsert VARCHAR2(1000); vQueryUpdate VARCHAR2(1000); vTableName VARCHAR2(30); Begin vTableName := FGETTABLENAME(POBJECTID => pObjectID); vQueryUpdate := 'UPDATE ' || vTableName || ' SET "VALUE" = :1'; vQueryInsert := 'INSERT INTO ' || vTableName || ' ("DTTIME", "VALUE") VALUES (:1, :2)'; EXECUTE IMMEDIATE vQueryInsert USING pDateTime, pValue; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN EXECUTE IMMEDIATE vQueryUpdate USING pValue; End; END "SPINSERTDATA"; 
  • 显然MERGE不起作用,因为TableName不能动态???
  • 我是新手,我的第三个月编码,我现在通过STACKOVERFLOW&Google搜索了3天,尝试各种有趣和绝望的解决方案……即使是一个非常相关的链接,如果你找到一个将是诚实的赞赏。

MERGE与Native动态SQL(EXECUTE IMMEDIATE)完美搭配:

 create table so_test(pk number not null primary key, value varchar2(20)); insert into so_test(pk, value) values(1, 'one'); declare l_SQL varchar2(4000); l_tablename varchar2(4000) default 'so_test'; begin l_SQL := 'merge into ' || l_tablename || ' target' || ' using (select 1 pk, ''eins'' value from dual union all select 2 pk, ''zwei'' value from dual) source on (target.pk = source.pk) when matched then update set target.value = source.value when not matched then insert values(source.pk, source.value) '; dbms_output.put_line(l_sql); execute immediate l_SQL; end; 

您能否发布使用MERGE时收到的错误消息?

您应该考虑编写此代码以使用静态SQL,而不是在运行时传递表名。 是否有正当理由说明为什么你不知道在运行期间你要合并到哪个表?

至于调试问题……

如何在代码中定义FGETTABLENAME函数? 这就是我提出的模仿那种情况的方法。 我建议使用%type(而不是RAW for Number Types)声明并从过程Names中删除Double Quotes。

  create or replace function FGETTABLENAME( POBJECTID in user_objects.object_id%type ) return user_objects.object_name%type as v_object_name user_objects.object_name%type; begin select object_name into v_object_name from all_objects where object_id = pobjectid; return v_object_name; end; / SQL> select object_id, object_name from user_objects; OBJECT_ID OBJECT_NAME ---------- -------------------------------------------- 52641 TFIVE 52644 SPINSERTDATA 52643 PROCEDURE 52645 FGETTABLENAME 52554 GET_SAL_EMP 52559 T1 SQL> select FGETTABLENAME(52641) from dual; FGETTABLENAME(52641) -------------------------------------------- TFIVE 

您可以在之后的代码中添加DBMS_OUTPUT.PUT_LINE语句

 vTableName := FGETTABLENAME(POBJECTID => pObjectID); and vQueryUpdate := 'UPDATE ' || vTableName || ' SET "VALUE" = :1'; vQueryInsert := 'INSERT INTO ' || vTableName || ' ("DTTIME", "VALUE") VALUES (:1, :2)'; 

或者跟踪代​​码以查看触发到数据库的实际SQL语句。

首先,您的UPDATE中没有WHERE,因此它将更新表的每一行。

其次,您是否使用了混合大小写表名称。 如果你做了

 CREATE TABLE "testOne" (ID NUMBER); 

然后表名将存储为testOne。 但是当你做一个UPDATE testOne ,它将被视为UPDATE TESTONE ,你将得到一个“没有这样的表”错误。

避免使用混合大小写表名称。 如果你绝对必须,那么你需要在动态SQL语句中引用它们