不允许时替代 MERGE INTO Oracle 语法的模式
我有一个应用程序,它使用 Oracle MERGE INTO...DML 语句来更新表 A,以与另一个表 B 中的一些更改相对应(表 A 是表 B 的选定部分以及一些其他信息的摘要)。在典型的合并操作中,可能会在表 B 中插入 5-6 行(数千行),并更新 2-3 行。
事实证明,应用程序将部署在对目标表具有安全策略的环境中。 MERGE INTO... 语句不能与这些表一起使用(ORA-28132:合并到语法不支持安全策略),
因此我们必须更改 MERGE INTO... 逻辑以使用常规插入和更新。这是其他人遇到过的问题吗?是否存在将 merge 语句中的 WHEN MATCHED/WHEN NOT MATCHED 逻辑转换为 INSERT 和 UPDATE 语句的最佳实践模式?合并是在存储过程中进行的,因此如果需要,除了 DML 之外,解决方案还可以使用 PL/SQL。
I have an application that uses the Oracle MERGE INTO... DML statement to update table A to correspond with some of the changes in another table B (table A is a summary of selected parts of table B along with some other info). In a typical merge operation, 5-6 rows (out of 10's of thousands) might be inserted in table B and 2-3 rows updated.
It turns out that the application is to be deployed in an environment that has a security policy on the target tables. The MERGE INTO... statement can't be used with these tables (ORA-28132: Merge into syntax does not support security policies)
So we have to change the MERGE INTO... logic to use regular inserts and updates instead. Is this a problem anyone else has run into? Is there a best-practice pattern for converting the WHEN MATCHED/WHEN NOT MATCHED logic in the merge statement into INSERT and UPDATE statements? The merge is within a stored procedure, so it's fine for the solution to use PL/SQL in addition to the DML if that is required.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
另一种方法(除了合并)是使用两个 sql 语句,一个用于插入,一个用于更新。 “WHEN MATCHED”和“WHEN NOT MATCHED”可以使用连接或“in”子句进行处理。
如果您决定采用以下方法,最好先运行更新(因为它仅针对匹配记录运行),然后插入非匹配记录。无论哪种方式,数据集都是相同的,它只是按以下顺序更新较少数量的记录。
此外,与合并类似,即使源和目标中的名称匹配,此更新语句也会更新名称列。如果您不想这样,也可以将该条件添加到 where 中。
可能有更好的方法来做到这一点,但这看起来很简单并且是面向 SQL 的。如果数据集很大,那么 PL/SQL 解决方案的性能不会那么好。
Another way to do this (other than Merge) would be using two sql statements one for insert and one for update. The "WHEN MATCHED" and "WHEN NOT MATCHED" can be handled using joins or "in" Clause.
If you decide to take the below approach, it is better to run the update first (sine it only runs for the matching records) and then insert the non-Matching records. The Data sets would be the same either way, it just updates less number of records with the order below.
Also, Similar to the Merge, this update statement updates the Name Column even if the names in Source and Target match. If you dont want that, add that condition to the where as well.
There could be better ways to do this, but this seems simple and SQL-oriented. If the Data set is Large, then a PL/SQL solution won't be as performant.
除了深入研究安全策略之外,我至少可以想到两个选择,而我对安全策略了解不多。
处理记录以逐行合并。尝试进行更新,如果更新失败则插入,反之亦然,具体取决于您是否期望大多数记录需要更新或插入(即针对最常见的情况进行优化,从而减少触发的 SQL 语句数量),例如:
另一种选择可能是批量收集要合并到数组中的记录,然后尝试批量插入它们,捕获所有主键异常(我现在不记得此语法,但您可以批量插入将所有无法插入的行放置到另一行中数组,然后处理它们)。
从逻辑上讲,合并语句必须在幕后检查每条记录是否存在,我认为它的处理方式与我上面发布的代码非常相似。然而,合并总是比用 PLSQL 编码更有效,因为它只需要 1 个 SQL 调用,而不是多次。
There are at least two options I can think of aside from digging into the security policy, which I don't know much about.
Process the records to merge row by row. Attempt to do the update, if it fails to update then insert, or vise versa, depending on whether you expect most records to need updating or inserting (ie optimize for the most common case that will reduce the number of SQL statements fired), eg:
Another option may be to bulk collect the records you want to merge into an array, and then attempted to bulk insert them, catching all the primary key exceptions (I cannot recall the syntax for this right now, but you can get a bulk insert to place all the rows that fail to insert into another array and then process them).
Logically a merge statement has to check for the presence of each records behind the scenes anyway, and I think it is processed quite similarly to the code I posted above. However, merge will always be more efficient than coding it in PLSQL as it will be only 1 SQL call instead of many.