UPSERT 到具有动态表名的表中
任何更好的 UPSERT 到表中的方法,前提是:
- 以约 1 行/秒的速度更新插入数据
- 表名称是动态的,使用传递给它的 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 不能是动态的 ???
- 我是一个新手,我编码的第三个月,我艰难地度过了 堆栈溢出与谷歌搜索了三天了,尝试了各种有趣的和有趣的内容。 绝望的解决方案......即使是一个非常相关的链接,如果你找到了一个 会受到真诚的赞赏。
Any better method to UPSERT into a table, provided :
- Data upsert at ~1 row/second
- Table Name is DYNAMIC, generated using ObjectID parameter passed to it
THE FOLLOWING PROCEDURE THROWS :
"ORA-00942: table or view does not exist"
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";
- Apparently MERGE does not work as the TableName Cannot be dynamic
??? - I'm a newbie, my third month of coding, I scourged through
STACKOVERFLOW & Googled for 3 days now, trying all sorts of funny &
desperate solutions ... Even a very relevant link if you found one
would be honestly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
MERGE 与本机动态 SQL(立即执行)完美配合:
您能否发布使用 MERGE 时收到的错误消息?
MERGE works perfectly fine with Native dynamic SQL (EXECUTE IMMEDIATE):
Could you please post the error message you get when using MERGE?
您应该考虑编写此代码以使用静态 SQL,而不是在运行时传递表名称。是否有正当理由导致您在运行时之前不知道要合并到哪个表中?
至于调试问题......
您的代码中函数 FGETTABLENAME 是如何定义的?这就是我模仿该场景的想法。我建议使用 %type (而不是数字类型的 RAW)声明并从过程名称中删除双引号。
您可以在代码中添加 DBMS_OUTPUT.PUT_LINE 语句
,或者跟踪代码以查看向数据库触发的实际 SQL 语句。
You should consider writing this to use Static SQL instead of passing the table name at Run Time. Is there a valid reason why you don't know what table you would be merging into till run-time?
As for debugging the issue...
How is the function FGETTABLENAME defined in your code? This is what I came up with which mimics that scenario. I would suggest Using %type (instead of RAW for Number Types) declarations and removing the Double Quotes from the procedure Names.
You can add DBMS_OUTPUT.PUT_LINE statements to your code after
or Trace your code to see the actual SQL statements being fired to your Database.
首先,您的 UPDATE 中没有 WHERE,因此它将更新表的每一行。
其次,您是否使用了大小写混合的表名。如果执行 a
,则表名将存储为 testOne。但是,当您执行
UPDATE testOne
时,将被视为UPDATE TESTONE
并且您将收到“no such table”错误。避免使用大小写混合的表名。如果绝对必须,那么您需要在动态 SQL 语句中引用它们
Firstly, you don't have a WHERE in your UPDATE so it will update every row of the table.
Secondly, have you used a mixed case table name. If you do a
then the table name will be stored as testOne. But when you do an
UPDATE testOne
is will be treated asUPDATE TESTONE
and you'll get a "no such table" error.Avoid using mixed case table names. If you absolutely must, then you'll need to quote them in the dynamic SQL statement