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语句中引用它们