Oracle:如何用详细信息表中的最新行更新主数据?
我们有两个表:
车辆:
- Id
- RegistrationNumber
- LastAllocationUserName
- LastAllocationDate
- LastAllocationId
Allocations:
- Id
- VehicleId
- UserName
- Date
用最新分配更新车辆表中的每一行的最有效(最简单)的方法是什么?在 SQL Server 中,我将使用 UPDATE FROM 并将每辆车加入最新的分配。 Oracle 没有 UPDATE FROM。在 Oracle 中如何做到这一点?
** 编辑 **
我要求最好的 SQL 查询进行更新。我将使用触发器来更新主表中的数据。我知道怎么写触发器。我所问的只是如何编写 SQL 查询来更新车辆表。例子会很好。谢谢。
We have two tables:
Vehicle:
- Id
- RegistrationNumber
- LastAllocationUserName
- LastAllocationDate
- LastAllocationId
Allocations:
- Id
- VehicleId
- UserName
- Date
What is the most efficient (easiest) way to update every row in Vehicle table with newest allocation? In SQL Server I would use UPDATE FROM and join every Vehicle with newest Allocation. Oracle doesn't have UPDATE FROM. How do you do it in Oracle?
** EDIT **
I am asking for best SQL query for update. I will be using trigger to update data in master table. I know how to write trigger. All I am asking is how to write SQL query to update Vehicle table. Example would be nice. Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
正如大多数其他人所指出的:由于您的数据模型,您遇到了一个大问题。为该模型编写的大多数代码将比需要的困难得多。我已经通过赞成票和反对票以及一些评论来表达了这一点,但这还不够。
如果您继续您的道路,那么下面的代码将演示需要完成的操作。希望它吓到你了:-)
示例表:
触发器必须查看它自己的表来确定最后的分配。 Oracle 通过引发变异表错误来防止这种类型的脏读。为了避免这种情况,我创建了一个 SQL 类型和一个包:
然后 3 个数据库触发器将更新代码从行级别移动到语句级别,从而避免了变异表错误:
并进行了一些测试来验证它是否在单用户环境中工作:
现在您所要做的就是添加一些序列化,使其在多用户环境中 100% 工作。但希望这个例子已经足够可怕了。
问候,
抢。
As indicated by most others: you have a big problem due to your data model. Most code written for this model, will be much more difficult than it needs to be. I've said it by up and downvoting and in some of the comments as well, but it can't be said enough.
If you continue on your path, then the code below demonstrates what needs to be done. Hopefully it scares you :-)
The sample tables:
The trigger would have to look into its own table to determine the last allocation. Oracle prevents this type of dirty reads by raising a mutating table error. To circumvent this I create a SQL type and a package:
Then 3 database triggers to move the update code from the row level to statement level, thus circumventing the mutating table error:
And a little test to verify that it works in a single user environment:
Now all you have to do is add some serialization to make it work 100% in a multi user environment. But hopefully the example was scary enough as it is.
Regards,
Rob.
当前设置要求您在 ALLOCATIONS 表上使用触发器来维护错误的决策选择。也就是说,使用:
通过从 VEHICLE 表中删除有问题的列,并使用视图提供最新的分配信息,可以更好地实现这一点。
The current setup requires you to use a trigger on the ALLOCATIONS table to maintain the poor decision choice. That said, use:
This would be better served by removing the offending columns from the VEHICLE table, and using a view to provide the latest allocation information.
从设计的角度来看,我更愿意在车辆表上主动维护这三个字段,并将“分配”填充为历史表(可能通过触发器)。将父表上的更新推送到子表上的插入比相反要容易得多。
From a design point of view, I'd prefer to have the three fields actively maintained on the Vehicle table, with the 'Allocations' populated as a history table (possibly by a trigger). A lot easier to push an update on a parent table down to an insert on a child than the other way around.
使用 Oracle 中的另一个表“更新”的最简单方法是使用 MERGE。
http://psoug.org/reference/merge.html
The easiest way to "update" using another table in Oracle is to use MERGE.
http://psoug.org/reference/merge.html
您是否在触发器内寻找更新?
Are you looking for the Update inside the Trigger?
你说得对。带有历史表的视图速度很慢。不存在快速“连接到最后一条记录”这样的事情。触发器是最好的解决方案。
如果可以的话,请在第一次时使用 PL 进行填充。它更容易理解和维护。
警告:写在这里,未经测试。
You're right. A View with a history table is slow. There is no such thing as a fast "join to last record". The trigger is the best solution.
If you can, use PL to populate the first time. It's easier to understand and mantain.
Warning: written here, not tested.