这是我得到的错误:
Msg 512,Level 16,State 1,Procedure tr_UpdateFolio,Line 361
子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。
我现在一遍又一遍地使用这段代码几个小时。我没看到什么?任何帮助,将不胜感激。我已经在这几天工作了,这几乎是我需要工作以完成这个项目的一件事。
-- 2. Write a trigger named tr_UpdateFolio that will be invoked when the Folio table 'status'
-- field ONLY (column update) is changed.
ALTER TRIGGER tr_UpdateFolio ON FOLIO--switch alter back to create
AFTER UPDATE
AS
IF UPDATE([Status])
BEGIN
DECLARE @Status char(1)
DECLARE @FolioID smallint
DECLARE @CheckinDate smalldatetime
DECLARE @Nights tinyint
DECLARE @CurrentDate smalldatetime = '7/27/2016 2:00:00 PM'
SELECT
@Status = i.Status,
@FolioID = i.FolioID,
@CheckinDate = i.CheckinDate,
@Nights = i.Nights
FROM
INSERTED i
-- If Folio status is updated to 'C' for Checkout, trigger two different Insert statements to
-- (1) INSERT in the Billing table, the amount for the total lodging cost as BillingCategoryID1
-- - (normally the FolioRate * number of nights stay, but you must also factor in any late checkout fees*).
-- *Checkout time is Noon on the checkout date. Guest is given a one hour
-- grace period to check out. After 1PM (but before 4PM), a 50% surcharge is added to the FolioRate. After 4PM, an
-- additional full night's FolioRate is applied. You can recycle code from A7 (part 5), but note it's not the exact same
-- function - we only need the late charge (if any).
IF @Status = 'C'
SET @Nights = 1
--@CurrentDate may need to switch back to getdate()
IF DATEDIFF(HOUR, @CheckinDate + @Nights, @CurrentDate) >= 16
SET @Nights = @Nights + 1
ELSE IF DATEDIFF(HOUR, @CheckinDate + @Nights, @CurrentDate) >= 13
SET @Nights = @Nights + .5
UPDATE FOLIO
SET Nights = @Nights
WHERE FolioID = @FolioID
INSERT INTO BILLING (FolioID, BillingCategoryID, BillingDescription, BillingAmount, BillingItemQty, BillingItemDate)
VALUES (25, 1, 'Room', dbo.GetRackRate(11, @CurrentDate) * @Nights, 1, @CurrentDate)
-- (2) The second INSERT statement in the same trigger will insert the Lodging Tax* - as a separate entry in the
-- Billing table for tax on lodging (BillingCategoryID2). *Use the dbo.GetRoomTaxRate function from A7 to determine
-- the Lodging Tax.
INSERT INTO BILLING (FolioID, BillingCategoryID, BillingDescription, BillingAmount, BillingItemQty, BillingItemDate)
VALUES (25, 2, 'Lodging Tax', dbo.GetRoomTaxRate(20), 1, @CurrentDate)
END
GO
-- 3. Write a trigger named tr_GenerateBill that will be invoked when an entry is INSERTED in to the Billing
-- table. If BillngCategoryID is 2 (for testing purposes only) then call the function dbo.ProduceBill (from A7).
ALTER TRIGGER tr_GenerateBill ON BILLING
AFTER INSERT
AS
BEGIN
DECLARE @FolioID smallint
DECLARE @BillingCategoryID smallint
SELECT @FolioID = i.FolioID, @BillingCategoryID = i.BillingCategoryID
FROM INSERTED i
IF @BillingCategoryID = 2
SELECT * FROM dbo.ProduceBill(@FolioID)
END
GO
dbo.producebill应该没问题,但是当我尝试运行此块
时会发生错误-- 4A. Assume today is (July 27, 2016 at 2PM)*. Anita is due to check out today (from Part 1 above).
-- Write an Update Statement to change the status of her Folio to 'CheckedOut.
-- (Be careful to include a WHERE clause so ONLY here folio is updated).
-- Note: This should automatically invoke tr_UpdateFolio above (factoring in the late charge),
-- which automatically invokes tr_GenerateBill above, and calls dbo.ProduceBill , and produces a bill.
UPDATE FOLIO
SET [Status] = 'C'
WHERE ReservationID = 5020
我很想解决这个问题。感谢。
答案 0 :(得分:0)
让我们从更简单的一个开始(tr_GenerateBill)。这个有点奇怪。您在插入触发器中有一个select语句。这意味着当您插入一行时,您希望它返回行。这不是插入的典型行为,但您可以使用它。
如果您插入3行,其中只有2行的BillingCategoryID为2,触发器应该做什么?该表的值函数是什么样的?
这是一种猜测,但你应该能够将整个触发器重写为这些内容。
ALTER TRIGGER tr_GenerateBill ON BILLING
AFTER INSERT
AS
BEGIN
SELECT *
FROM inserted i
cross apply dbo.ProduceBill(i.FolioID) pb
where i.BillingCategoryID = 2
END
你的第二次触发更具挑战性。你在这里尝试做什么并不完全清楚,但我认为这非常接近。
UPDATE f
set Nights = case when DATEDIFF(HOUR, @CheckinDate + i.Nights, @CurrentDate) >= 16 then 2 else 1 end --adding .5 to a tiny int is pointless. It will ALWAYS be the same value.
from inserted i
join Folio f on f.FolioID = i.FolioID
INSERT INTO BILLING (FolioID, BillingCategoryID, BillingDescription, BillingAmount, BillingItemQty, BillingItemDate)
Select i.FolioID
, 1
, 'Room'
, dbo.GetRackRate(11, @CurrentDate) * case when DATEDIFF(HOUR, @CheckinDate + i.Nights, @CurrentDate) >= 16 then 2 else 1 end, 1, @CurrentDate)
from inserted i
INSERT INTO BILLING (FolioID, BillingCategoryID, BillingDescription, BillingAmount, BillingItemQty, BillingItemDate)
select i.FolioID
, 2
, 'Lodging Tax'
, dbo.GetRoomTaxRate(20), 1, @CurrentDate)
from inserted i