将值、NULL 或不更新此列传递给 Oracle 表更新存储过程?
Posted
技术标签:
【中文标题】将值、NULL 或不更新此列传递给 Oracle 表更新存储过程?【英文标题】:Passing value, NULL or don't-update-this-column to an Oracle table update stored procedure? 【发布时间】:2013-05-28 18:57:23 【问题描述】:我想编写一个 Oracle 存储过程来更新数据库上的表,其中有一种方法可以为该过程提供(或不提供)一个 columname 参数意味着“不更新此列”。这和
不太一样 更新表名集 列名 = nvl(p_columnname,列名), ... 其中键 = p_key如果您这样做,则不能将该列清空。我也希望能够取消该列。如果 Oracle 支持无类型关键字 UNKNOWN,我可以说 p_columname varchar2 := UNKNOWN,并测试自定义函数中参数的遗漏。但如果没有这个,定义魔法值会变得很麻烦,这意味着“不要更新该列”,每个数据类型一个,这样我就不会在比较不兼容的数据类型时出错。
这似乎是一个常见的问题(一个存储过程来处理对表的所有更新,而不需要对未更改的列进行 read-before-write 选择)。肯定有人想出了一个最佳实践来处理它。无论如何希望如此。提前致谢。
【问题讨论】:
我个人会使用不同的存储过程每个事务,以及该用例所需的确切 SQL(当然,如果需要,使用辅助存储过程)。我发现“表”存储过程不是很有用(我必须承认我接触过高剂量的asktom.oracle.com) 我同意。我只在必要时才使用表存储过程,要么(a)因为更新很棘手,要么(b)我的客户有一个标准来指示它们的使用。无论哪种方式,实现表存储过程的原因是将处理逻辑移动到数据库,如果调用者必须将一堆列设置为 null 或其他似是而非的值,这表明处理逻辑已经从数据库中消失了。我也会为每笔交易推荐不同的程序,并将它们放入一个包中。如果你愿意,你可以给它们起相同的名字——Oracle 支持重载。 感谢您这么快回复。不幸的是,我不决定更新哪些列。客户这样做了,并向我发送了仅包含更改的列的最小 XML。为每个可能的列组合创建一个存储过程将是一个组合爆炸。 【参考方案1】:这里需要在一方面提供完全集中的更新,另一方面通过更新所有内容来简化开发之间取得平衡。它们都可能对性能产生负面影响。
当您更新每一列时,显然会增加重做、撤消、重做日志负载增加、等待日志文件同步时间更长、可能进行多余的外键值检查等方面的开销。性能不佳通常等于时间损失由开发人员进行故障排除和重新开发。
但是,另一方面,如果每次更新都完全集中,那么您现在可能有五个、十个、二十个等,而不是共享池中的一个更新语句 - 但是可以进行多种更改组合。这本身就是一件坏事,可能会导致硬解析增加,并导致稍后在故障排除中浪费时间。
中间立场可能是尝试识别更常见的更新类型(例如,更改电话号码、更新订单状态等)并为这些更新提供专门的更新,并将其余的(希望是少数)发送到一般更新。
要格外小心,您可能会考虑记录每 60 次使用常规更新以准确查看发生了什么变化,并尝试通过检查来找出任何意外的常见组合(或使用错误更新 API 的开发人员):
extract(second from systimestamp) < 1
...什么的。
【讨论】:
感谢您这么快回复。不幸的是,要更新的列没有任何模式。我保留传入 XML 的审计跟踪,并可以构建 XML 标记的相关矩阵(映射到数据库列)。当然,在过程中检测“不更新此列”条件会更好。 您认为有多少独特的更新组合?【参考方案2】:如果要有条件地设置列,可以使用 case 语句来实现:
update table
set column = case
when <your condition here> then
column
else
parameter
end
当您的“不更新条件”满足时,这会将列设置为自身(即不更新)。您需要决定需要哪些参数来识别它。与 nvl 相比,它提供的优势是允许您在需要时将列设置为 null。
【讨论】:
以上是关于将值、NULL 或不更新此列传递给 Oracle 表更新存储过程?的主要内容,如果未能解决你的问题,请参考以下文章