You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server多CTE存储过程报错:无效对象名'report_cte'

问题原因与解决方案

根本问题

CTE(公用表表达式)的作用域仅限定义完成后的第一条SQL语句。你的代码中,在report_cte定义结束后先执行了DELETE操作,此时CTE的生命周期已结束,后续INSERT语句再调用report_cte就会提示找不到对象。

修复方案

将DELETE语句移至CTE定义之前执行,确保CTE定义后紧跟需要调用它的INSERT语句:

ALTER PROCEDURE Sp_Inventory_PrMonth
    (@currentdate DATE)
AS
BEGIN
    DECLARE  @first_day_prior_month DATE, @last_day_prior_month DATE;

    -- Calculate the first and last day of the prior month
    SET @first_day_prior_month = DATEADD(mm, DATEDIFF(mm, 0, @currentdate) - 1, 0); 

    SET @last_day_prior_month = EOMONTH(@first_day_prior_month);

    -- 先执行删除操作,不影响后续CTE的作用域
    DELETE FROM [dbo].[Floorplan_Summary]
    WHERE [Period] = CONVERT(varchar(6), @first_day_prior_month, 112);

    -- 定义CTE,之后直接执行INSERT调用它
    ;WITH [dates_cte] AS 
    (
        SELECT * 
        FROM (VALUES ('2019-09-01', '2019-09-30', '201909'),
                     ('2022-10-01', '2022-11-01', '202210'),
                     ('2022-11-01', '2022-12-01', '202211')) AS [t]([start_date], [end_date], [period])
    ),
    [inventory_cte] AS
    (
        SELECT
            [vi].[database_id],
            [YYYYMM] = [d].[period],
            [State] = CASE 
                          WHEN [vi].[database_id] LIKE 'STORE4%' 
                              THEN 'QLD' 
                              ELSE 'NSW' 
                      END,
            [vi].[nkey],
            [Type] = CASE 
                         WHEN [vi].[VehicleInventoryTypeID] = 'Used' 
                             THEN 'Used'
                             ELSE CASE 
                                      WHEN ([vi].[StatusID] IN ('4', '7', '8') OR ([vi].[StatusID] IN ('6', '13') AND [vi].[PreSaleStatusID] IN ('4', '7', '8'))) 
                                          THEN 'Demo'
                                          ELSE 'New' 
                                  END
                     END,
           [Location_Code] = [vi].[database_id] + '_' + [vi].[LocationID],
           [Make] = CASE 
                        WHEN [vi].[VehicleInventoryTypeID] = 'Used' 
                            THEN 'Used' 
                            ELSE [vi].[ManufacturerID] 
                    END,
           [vi].[StatusID],
           [vi].[ReceiptDate],
           [vi].[DeliveryDate],
           [vi].[ActivityDate],
           [vi].[CostAmount],
           [Vi].[VehicleInventoryTypeID]
       FROM
           [PDW_SQLSERVER].[510102_DataWarehouse].[dbo].[VehicleInventory] AS [vi]
       INNER JOIN
           [dates_cte] AS [d] ON [vi].[ReceiptDate] < [d].[end_date]
                              AND (([vi].[StatusID] NOT IN ('6', '13'))
                                   OR ([vi].[StatusID] IN ('6') AND [vi].[DeliveryDate] > [d].[end_date])
                                   OR ([vi].[StatusID] IN ('13') AND [vi].[ActivityDate] > [d].[end_date]))
                              AND [vi].[StatusID] NOT IN ('9')
                              AND [vi].[LocationID] NOT IN ('ORD', 'NHY', 'CHTA', 'SMA')
       WHERE 
           [vi].[database_id] IN ('STORE201', 'STORE214', 'STORE217', 'STORE401')
    ),
    [report_cte] AS
    (
        SELECT 
            [i].[YYYYMM],
            [i].[State],
            [i].[Location_Code],
            [i].[Make],
            [i].[Type],
            [i].[nkey],
            [i].[CostAmount]
        FROM 
            [inventory_cte] AS [i]
    )
    -- Insert the data for the prior month into the table
    INSERT INTO [dbo].[Floorplan_Summary]
                     ([Period], [State], [Location_Code], [Make],[Type],
                      [Floorplan_Unit_Count], [Floorplan_Cost_Amount])
        SELECT
            [t].[YYYYMM], [t].[State], [t].[Location_Code],
            [t].[Make], [t].[Type],
            [n] = COUNT([t].[nkey]), 
            [Total] = SUM([t].[CostAmount])
        FROM
            [report_cte] AS [t]
        WHERE
            [t].[YYYYMM] = CONVERT(varchar(6), @first_day_prior_month, 112)
        GROUP BY
            [t].[YYYYMM], [t].[State], [t].[Type],
            [t].[Location_Code], [t].[Make]
    END

    --execute Sp_Inventory_PrMonth '2022-12-10'

补充说明

如果后续需要CTE同时支撑多个操作(比如DELETE和INSERT都依赖CTE数据),可以先将CTE结果存入临时表,再基于临时表执行后续操作,彻底规避作用域限制。

内容的提问来源于stack exchange,提问作者shima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:25:26