【问题标题】:SQL Server temp table cannot be created but doesn't existSQL Server 临时表无法创建但不存在
【发布时间】:2018-09-23 00:42:19
【问题描述】:

请原谅我,我很少使用大型 SQL Server 存储过程,但我在使用以下存储过程时遇到了相当大的问题。

基本上,我正在尝试手动运行包含联合的查询,并将其放入带有游标的存储过程中,并将结果返回到临时表中。但是,我收到一个错误,即无法创建临时表,因为它“已经存在”(我已经运行检查它是否存在,但它不存在)或者我没有权限(我这样做是因为我以 SQL 管理员身份登录)。我到底做错了什么?

我运行了以下查询以查看它是否确实存在于 tempdb 和正在创建存储过程的位置,它返回 else 语句:

IF OBJECT_ID('IPAM..#tempschedule') IS NOT NULL
BEGIN
    PRINT '#temp exists!'
END
ELSE
BEGIN
    PRINT '#temp does not exist!'
END

这是我要更改的存储过程:

ALTER PROCEDURE lakearrowhead_schedule_python
AS
    IF OBJECT_ID('tempdb..#tempschedule') IS NOT NULL
    BEGIN
        DROP TABLE #tempschedule;
    END;

    CREATE TABLE #tempschedule
    (
        ProgramID INT,
        ItemID INT,
        Day SMALLINT,
        [Date] DATE,
        [Begin TIME] VARCHAR(15),
        [End TIME] VARCHAR(15),
        TIMESLOT NVARCHAR(11),
        SLOTTYPE INT,
        SlotTypeDescription NVARCHAR(64),
        SLOTINFO INT,
        SlotInfoDescription NVARCHAR(500),
        TalkID INT,
        Talk NVARCHAR(50),
        FIRSTNAME NVARCHAR(20),
        LASTNAME NVARCHAR(50),
        INSTITUTION NVARCHAR(150),
        AUTHORLINE NVARCHAR(384),
        TITLE NVARCHAR(256),
        Abstract VARCHAR(1),
        [LOCATION] INT,
        ADDENDUM TEXT,
        EventName NVARCHAR(256)
    );

    DECLARE @pid INT;

    DECLARE PROGRAM_cursor CURSOR FOR
        SELECT TOP 3 WebEvents.EventID
        FROM WebEvents
        INNER JOIN dbo.WebPrograms ON dbo.WebEvents.EventID = dbo.WebPrograms.ProgramID
        WHERE EventLocation = 1004
          AND (eventstartdate >= GETDATE())
        ORDER BY 
            eventstartdate, ProgramCode;

    OPEN PROGRAM_cursor;

    FETCH NEXT FROM PROGRAM_cursor INTO @pid;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT *
        INTO #tempschedule
        FROM 
            (SELECT 
                 WS.ProgramID ,
                 WS.ItemID ,
                 WS.Day ,
                 CASE DATEPART(WEEKDAY, DATEADD(DAY, WS.Day - 1, WE.eventstartdate))
                     WHEN 1 THEN 'Sun'
                     WHEN 2 THEN 'Mon'
                     WHEN 3 THEN 'Tue'
                     WHEN 4 THEN 'Wed'
                     WHEN 5 THEN 'Thu'
                     WHEN 6 THEN 'Fri'
                     WHEN 7 THEN 'Sat'
                     ELSE 'N/A'
                 END + ' ' + CONVERT(CHAR(12), DATEADD(DAY, WS.Day - 1, WE.eventstartdate), 101) AS Date,
                 CONVERT(VARCHAR(15), CONVERT(TIME, SUBSTRING(WS.TimeSlot, 0, 6)), 100) AS 'Begin TIME',
                 CONVERT(VARCHAR(15), CONVERT(TIME, SUBSTRING(WS.TimeSlot, 7, 6)), 100) AS 'End TIME',
                 WS.TimeSlot,
                 WS.SlotType,
                 WSSTC.Description AS SlotTypeDescription,
                 WS.SlotInfo,
                 WSSIC.Description AS SlotInfoDescription,
                 ISNULL(WSI.TalkID, 0) AS TalkID,
                 LEFT(WPI.FirstName, 10) + ' '
                     + LEFT(WPI.LastName, 10) + ' ('
                     + LEFT(WEA.institution, 10) + ')' + ' - '
                     + LEFT(WSI.Title, 10) + '...'
                     + RIGHT(WSI.Title, 10) AS Talk,
                 WPI.FirstName,
                 WPI.LastName,
                 WEA.institution,
                 WSI.AuthorLine,
                 WSI.Title,
                 LEFT(WSI.Abstract, 1) AS Abstract,
                 WS.Location,
                 WS.Addendum,
                 WE.EventName
             FROM   
                 dbo.WebSpeakerInfo WSI
             INNER JOIN 
                 dbo.WebPersonalInfo WPI ON WSI.UserID = WPI.UserID
             INNER JOIN 
                 dbo.webeventaffiliation WEA ON WPI.UserID = WEA.userid
                                             AND WEA.eventid = @pid
             RIGHT OUTER JOIN 
                 dbo.WebScheduleSlotTypeCodes WSSTC 
             RIGHT OUTER JOIN 
                 dbo.WebSchedules WS ON WSSTC.SlotType = WS.SlotType 
                 ON WSI.TalkID = WS.TalkID
             LEFT OUTER JOIN 
                 dbo.WebScheduleSlotInfoCodes WSSIC ON WS.SlotInfo = WSSIC.SlotInfo
             INNER JOIN 
                 dbo.WebEvents WE ON WE.EventID = @pid
             WHERE  
                 WS.ProgramID = @pid
                 AND WS.SlotType <> 6 ) AS x
            ORDER BY 
                 Day, TimeSlot;

        FETCH NEXT FROM PROGRAM_cursor INTO @pid;
    END;

    CLOSE PROGRAM_cursor;
    DEALLOCATE PROGRAM_cursor;

    SELECT *
    FROM #tempschedule;

    DROP TABLE #tempschedule;

【问题讨论】:

  • 看起来您的检查语句正在查看与 tempdb 不同的数据库,还是我遗漏了什么?
  • @AnthonyHancock 我尝试了 tempdb,但也检查了该过程进入的数据库(IPAM),以防服务器出于某种奇怪的原因将其放入其中。它卡在 SQL lala 的内存中某处,因为我找不到它
  • 您使用的是什么版本的 SQL Server?
  • 我不记得具体情况,但我遇到过几次类似的情况。我只是在没有 if 语句的情况下自行运行 drop 表,然后重新运行所有内容,它通常可以工作。可以试试。
  • @AnthonyHancock SQL Server 2017,大声笑我也尝试在没有任何检查或任何东西的情况下删除表,但仍然没有工作。

标签: sql-server tsql stored-procedures cursor temp-tables


【解决方案1】:

当您运行ALTER 语句时,您正在将存储过程转换为以下语句:

ALTER PROCEDURE lakearrowhead_schedule_python
AS
    IF OBJECT_ID('tempdb..#tempschedule') IS NOT NULL
        BEGIN
            DROP TABLE #tempschedule;
        END;

其余语句只是在ALTER之后执行。

故事的寓意? 总是对存储过程、函数和触发器使用BEGIN/END 块。

我应该注意,存储过程结束时会自动删除临时表。通过使用表变量,您可以更加确定。这些都已删除且超出范围。因此,在存储过程的主体中不需要显式删除临时表。

【讨论】:

  • 好吧,这是有道理的,所以通过在“AS”之后放置一个 BEGIN 并在“DROP TABLE #tempschedule;”之后放置一个 END错误应该消失正确吗?还是我的问题不仅仅如此?我添加了 BGIN 和 END,但仍然收到错误消息 2714,级别 16,状态 1,过程lakearrowhead_schedule_python,第 49 行 [批处理开始行 0] 数据库中已经有一个名为“#tempschedule”的对象。消息 156,级别 15,状态 1,过程lakearrowhead_schedule_python,第 111 行 [批处理开始行 0] 关键字“AS”附近的语法不正确。
  • 是的,我觉得很奇怪,我必须在存储过程结束时删除临时表。
  • 我什至删除了 SP 并尝试创建而不是更改,但我仍然收到错误。哈哈,这令人沮丧。我可能不得不走另一条路,但从我的网络应用程序中传入 3 个 ID 并运行原始的 Union 查询。
猜你喜欢
  • 2017-07-19
  • 2020-02-13
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
相关资源
最近更新 更多