【问题标题】:Using Multiple CTE with one INSERT statement. [Error:More Columns than Specified in Column List]将多个 CTE 与一个 INSERT 语句一起使用。 [错误:列列表中的列多于指定的列]
【发布时间】:2018-04-01 15:25:03
【问题描述】:

我有如下 CTE1 和 CTE2。 CTE2显示错误

CTE2 has more columns than specified in the column list

我想知道我做错了什么。这不可能是因为 Insert 语句的列数比 CTE2 多,因为 CTE1 之前工作正常。 CTE1 和 CTE2 都使用不同的表。是这个问题吗?

如果我删除CTE2(NewRoomCost,NewQuantity) 中的参数,则会出现错误

No Columns specified for Column3 of CTE2

以下是我尝试过的代码。任何帮助将不胜感激。

CREATE PROCEDURE dbo.SpTransactionGenerate
AS
BEGIN
SET NOCOUNT ON

    DECLARE @MinReservationId INT = (SELECT MIN(f.ReservationId) FROM dbo.Reservation AS f)
    DECLARE @MaxReservationId INT = (SELECT MAX(f.ReservationId) FROM dbo.Reservation AS f)

    DECLARE @FirstSeasonEndDate DATE= '2018-02-13';
    DECLARE @SecondSeasonEndDate DATE='2018-02-14';
    DECLARE @ThirdSeasonEndDate DATE='2018-12-31';

    WHILE @MinReservationId<=@MaxReservationId
    BEGIN   
        WITH CTE1(ServiceId,ServiceRate,Quantity) AS 
        (
           SELECT ServiceId,
                  ServiceRate,
                  ABS(CHECKSUM(NEWID())%3) + 1 AS Quantity 
           FROM dbo.[Service]                              
        ),
        CTE2(NewRoomCost,NewQuantity) AS 
        (
           SELECT 
                (SELECT roomRate.RoomCost FROM dbo.RoomRate as roomRate WHERE roomRate.RoomTypeId=
                (SELECT room.RoomTypeId FROM dbo.Room as room
                JOIN dbo.Reservation as res ON res.RoomId=room.RoomId WHERE res.ReservationId=@MinReservationId
                AND roomRate.SeasonId=(
                CASE WHEN (SELECT resv.CheckInDate FROM dbo.Reservation as resv WHERE resv.ReservationId=@MinReservationId)<=@FirstSeasonEndDate
                THEN (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=@FirstSeasonEndDate)
                WHEN (SELECT resv.CheckInDate FROM dbo.Reservation as resv WHERE resv.ReservationId=@MinReservationId)<=@SecondSeasonEndDate
                THEN (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=@SecondSeasonEndDate)
                ELSE (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=@ThirdSeasonEndDate) END
                )
                )) AS NewRoomCost,

                DATEDIFF(DAY,(SELECT r.CheckinDate FROM dbo.Reservation AS r WHERE r.ReservationId=@MinReservationId), (SELECT r.CheckOutDate FROM dbo.Reservation AS r WHERE r.ReservationId=@MinReservationId)) AS NewQuantity,                                                  
        )

        INSERT INTO dbo.[Transaction]
        (
            ReservationId,
            ServiceId,
            Rate,
            Quantity,
            Amount              
        )   
        SELECT 
            @MinReservationId,
            ServiceId,
            ServiceRate,
            Quantity,
            ServiceRate*Quantity
            FROM CTE1
            UNION
        SELECT 
            @MinReservationId,
            NULL,
            NewRoomCost,
            NewQuantity,
            NewRoomCost*NewQuantity
            FROM CTE2

        SELECT @MinReservationId=@MinReservationId+1    
    END
END

更新:由于 CTE2 中有一个额外的逗号导致错误。很抱歉提出了不必要的问题。

【问题讨论】:

  • 为什么是 ctes 和 union。直接做两次插入即可。
  • @paparazzo 因为我需要在同一个 select 语句中使用最近插入的 Rates 和 Quantities 的值。如果有更好的方法,请指导我。 :)
  • 但是您没有使用第二个中第一个 cte 的值。
  • @paparazzo stackoverflow.com/q/49584549/9139132 是我使用 CTE1 的原因
  • 我放弃了。 CTE 在这里没有任何价值。你可以直接插入。

标签: sql sql-server database sql-server-2016


【解决方案1】:

CTE2 中的问题是您在此行末尾多了一个逗号:

DATEDIFF(DAY,(SELECT r.CheckinDate FROM dbo.Reservation AS r WHERE r.ReservationId=@MinReservationId), (SELECT r.CheckOutDate FROM dbo.Reservation AS r WHERE r.ReservationId=@MinReservationId)) AS NewQuantity, 

旁注:我建议以后不要写明确的列名,而只是像使用 AS 关键字那样命名它们。它只是总体上提供了更大的灵活性。

【讨论】:

    【解决方案2】:

    因为您的第二个 CTE 定义了两列:

    CTE2(NewRoomCost,NewQuantity) AS
    

    但是您的 select 语句返回 3。

    (SELECT roomRate.RoomCost FROM...
    
    DATEDIFF(DAY,(SELECT r.CheckinDate...
    
    (SELECT r.CheckOutDate FROM dbo.Reservation...
    

    【讨论】:

    • (SELECT r.CheckOutDate FROM dbo.Reservation... 不是包含在 DATEDIFF ( datepart , startdate , enddate )
    • 我相信你只是在 DATEDIFF 的末尾多了一个逗号。
    • @MK_ 是的,感觉很愚蠢:|我无法删除问题,因为重复删除会阻止我提出未来的问题。啊!!我只是要在问题中编辑它。
    • @SudeepShrestha - 没关系,这样的错误往往会发生。我建议我写一个答案,您将其标记为解决方案,这将是案例关闭。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2021-11-26
    • 1970-01-01
    相关资源
    最近更新 更多