约束将一列自动设置为另外两列的总和

时间:2014-04-23 19:34:15

标签: oracle

我想知道是否可以使用约束将一列的值设置为另外两列的总和。例如,给出以下表格:

CREATE TABLE Room (
Room_Num NUMBER(3),
Room_Band_ID NUMBER(2),
Room_Type_ID NUMBER(2),
Room_Price NUMBER(4),
PRIMARY KEY (Room_Num),
FOREIGN KEY(Room_Band_ID)
REFERENCES Room_Band(Room_Band_ID),
FOREIGN KEY(Room_Type_ID)
REFERENCES Room_Type(Room_Type_ID)
);


CREATE TABLE Booking (
Booking_ID NUMBER(10) NOT NULL,
GuestID NUMBER(4) NOT NULL,
StaffID NUMBER(2) NOT NULL,
Payment_ID NUMBER(4) NOT NULL,
Room_Num NUMBER(3) NOT NULL,
CheckInDate DATE NOT NULL,
CheckOutDate DATE NOT NULL,
Booking NUMBER(2) NOT NULL,
Price NUMBER(4),
PRIMARY KEY (Booking_ID),
FOREIGN KEY(GuestID)
REFERENCES Guest(GuestID),
FOREIGN KEY(StaffID)
REFERENCES Staff(StaffID),
FOREIGN KEY(Payment_ID)
REFERENCES Payment(Payment_ID),
FOREIGN KEY(Room_Num)
REFERENCES Room(Room_Num)
);

我知道可以这样做:

   Constraint PriceIs CHECK (Booking.Price=(Room.Room_Price*
   (Booking.CheckOutDate - Booking.CheckInDate)));

是否也可以设置一个不仅确保价格正确的约束,而是自动将价格计算到相关元组的价格字段中?

更新

所以我尝试按如下方式设置触发器:

   CREATE OR REPLACE trigger PriceCompute
   AFTER INSERT ON Booking
   FOR each row
   BEGIN
   UPDATE Booking
   SET 
   SELECT (Room.Room_Price*(Booking.CheckOutDate - Booking.CheckInDate))
   INTO
   Booking.Price
   FROM Booking
   JOIN ROOM ON Booking.Room_Num = Room.Room_Num
   END;
   /

但是我收到了以下错误: Cmd prompt errors returned from trigger compilation

任何人都可以看到我在这里误入歧途的地方,因为它超越了我。

3 个答案:

答案 0 :(得分:1)

我认为您必须在两个牌桌上设置触发器,以便每当房间的价格值发生变化或结账/入场日期发生变化时,它都会更新您的计算中的PriceIs字段。

如果您不需要存储在实际字段中的计算部分,您始终可以创建一个视图,只要您查看视图就可以计算它。

答案 1 :(得分:1)

是的,你可以。这是你的选择。按个人喜好排列:

  1. 您可以拥有一个没有此列的表格。并创建一个将动态计算此列的视图。

  2. 您可以使用oracle虚拟列

    create table  Room (
    ...
    price     NUMBER GENERATED ALWAYS AS (room_price*(checkOut-checkIn)) VIRTUAL,
    ...)
    
  3. 您可以使用实际列(与Dave Costa相同):

    create table  Room (
    ...
    price     AS (room_price*(checkOut-checkIn)),
    ...)
    
  4. 您可以编写触发器来填充它(如Mat M建议的那样)

  5. 您可以编写存储过程,但在这种情况下会出现过度杀伤

答案 2 :(得分:1)

我认为更好的解决方案是使用一个可以动态计算值的视图。但是关于尝试创建触发器,您应该使用:new.<column_name>来引用插入Booking表的值。您不需要在该表上执行更新和查询以获取或修改正在插入的行中的值*。您只需将它们称为变量即可。所以你想要做的事情如下:

SELECT (Room.Room_Price*(:new.CheckOutDate - :new.CheckInDate))
   INTO
   :new.Price
   FROM ROOM WHERE :new.Room_Num = Room.Room_Num

*实际上,您无法对其修改首先调用触发器的表执行查询或更新。你会得到臭名昭着的变异表&#34;如果您的触发器实际编译并运行,则会出错。