【发布时间】:2014-04-17 03:28:38
【问题描述】:
过去几周我一直在尝试使用 Oracle,但偶然发现了一个我似乎无法解决的问题。
我正在构建一个小型物业管理系统,我正在尝试在数据库端处理尽可能多的操作(纯粹是实验性的,我只是想在有人问之前澄清这一点,“你为什么不通过更新这些行客户”)
在我的系统中,我有一个属性和房间表(下面的简化架构):
`-------------------------------
` PROPERTIES
`-------------------------------
`- PropertyID: PK
`- PropertyStatus: VARCHAR
`-------------------------------
`-------------------------------
` ROOMS
`-------------------------------
`- RoomID: PK
`- PropertyID: FK
`- RoomStatus: VARCHAR
`-------------------------------
每当用户被分配到一个房间时,房间状态都会更新为OCCUPIED,一旦发生这种情况,我想检查有多少与属性n相关的房间被占用,如果所有房间都被占用,property_status 应该被更新到 FULL,然后如果用户未从属性中分配,则值更新为 VACANCIES AVAILABLE 等。
我已经制定了这个的基本逻辑:
-- Return how many vacant rooms belong to this property
CREATE OR REPLACE FUNCTION prop_vacancy_query(
p_property_id properties.property_id%TYPE
)
RETURN NUMBER
IS
v_prop_rooms NUMBER;
BEGIN
SELECT COUNT(room_status)
INTO v_prop_rooms
FROM rooms
JOIN properties ON
rooms.property_id = properties.property_id
WHERE room_status = 'VACANT'
AND rooms.property_id = p_property_id;
RETURN v_prop_rooms;
END prop_vacancy_query;
在我的房间表上的 AFTER 触发器中,我尝试调用查询,但我得到一个变异表错误,我相信这是因为 prop_vacancy_query 正在读取属性表。
CREATE OR REPLACE TRIGGER trg_rooms_after
AFTER INSERT OR UPDATE ON rooms FOR EACH ROW
BEGIN
-- Update the table based on the result
IF prop_vacancy_query(:NEW.property_id) = 0 THEN
UPDATE properties
SET prop_status = 'VACANT'
WHERE properties.property_id = :NEW.property_id;
ELSE
UPDATE properties
SET prop_status = 'FULL'
WHERE properties.property_id = :NEW.property_id;
END IF;
END;
以前这段代码适用于我的系统,但自从阅读更多 pragma autonomous transactions 后,我意识到在自己的独立事务上运行 prop_vacancy_query() 是非常糟糕的做法。
有什么方法可以从属性表中读取,然后更新房间表而不会出现变异错误?
【问题讨论】: