简体   繁体   English

存储过程中的“无效的列名”

[英]'Invalid column name' from within a stored procedure

I wrote a stored procedure to insert future dates (excluding Sat and Sun) into a permanent table. 我编写了一个存储过程,以将将来的日期(星期六和星期日除外)插入永久表。 The routine uses just one temp table. 该例程仅使用一个临时表。 The purpose of this post is not to critique the Stored Procedure. 这篇文章的目的不是批评存储过程。 Although, I am certain it could be improved. 虽然,我相信它可以改善。 However, the purpose of this post is to analyze why the stored procedure is throwing these errors when called under one set of circumstances and not others. 但是,本文的目的是分析为什么在一组情况下而非其他情况下调用存储过程时会引发这些错误。

1 - Here are the errors I receive 1-这是我收到的错误

Msg 207, Level 16, State 1, Procedure MAKE_FUTURE_DATES, Line 25
Invalid column name 'tdate'.
Msg 207, Level 16, State 1, Procedure MAKE_FUTURE_DATES, Line 31
Invalid column name 'wday'.

2 - Here is the stored procedure 2-这是存储过程

ALTER PROCEDURE [dbo].[MAKE_FUTURE_DATES] (@STARTDATE DATE)
AS
BEGIN
-- We need to populate FUTURE_DATES (table) with forward looking dates (week days only) 
-- We do not consider/exclude holidays here. We just exclude Sat/Suns

-- Temp table to hold the dates and days of the week
    CREATE TABLE #TMP_DATES(
        [tdate] [date] NULL,
        [wday] [varchar](10) NULL,  
        )

    -- To generate 'enough' future dates loop up to 1199 days in the future
    -- and insert dates that start with the current date and increase with each loop

    DECLARE @Loop INT
    SET @Loop = 0
    WHILE @Loop < 1200
    BEGIN
        INSERT INTO #TMP_DATES (tdate) VALUES (DATEADD(weekday,@Loop,@STARTDATE))   
        SET @Loop = @Loop + 1
    END

    -- Now update the wday column with the weekday name so we can get rid of
    -- Sat/Sun in the next step

    UPDATE #TMP_DATES
    SET wday = UPPER(LEFT(DATENAME(dw,tdate),3))

    -- Get rid of Sat/Sun
    DELETE FROM #TMP_DATES WHERE wday = 'SAT' or wday = 'SUN'

    -- Now clear the final destination table
    TRUNCATE TABLE FUTURE_DATES

    -- Insert the weekday dates into future_dates

    INSERT INTO FUTURE_DATES (fdate,wday)
    SELECT tdate,wday FROM #TMP_DATES

    DROP TABLE #TMP_DATES

3 - I have been calling the above stored procedure within another stored procedure as a SQL Server task in the background (via the SQL Server job scheduler) for about 6 months without any errors or problems. 3-我已经在另一个存储过程中将上述存储过程作为后台SQL Server任务(通过SQL Server作业计划程序)在后台调用了大约6个月,没有任何错误或问题。 More recently, I created a new stored procedure, let's call it 'ABC', that calls a stored procedure that calls MAKE_FUTURE_DATEs. 最近,我创建了一个新的存储过程,我们称之为“ ABC”,它调用了一个存储过程,该存储过程调用了MAKE_FUTURE_DATE。

4 - Here is the part I am trying to solve. 4-这是我要解决的部分。 When ABC is invoked as a SQL Server task in the background (via the SQL Server job scheduler) it throws the errors every time (which is daily) and the results are not produced/it crashes. 当在后台(通过SQL Server作业计划程序)将ABC作为SQL Server任务调用时,它每次(每天)都会引发错误,并且不会产生结果/它会崩溃。 When I first start up SQL Server Management Studio and run ABC it sometimes throws the error the first time. 当我第一次启动SQL Server Management Studio并运行ABC时,有时会第一次抛出错误。 The second time in this sequence and all subsequent times it does not throw the error. 此序列中的第二次以及以后的所有第二次都不会引发错误。 Also, keep in mind that the stored procedure that has been calling MAKE_FUTURE_DATES for 6 months is still quite happy with no errors. 另外,请记住,已调用MAKE_FUTURE_DATES 6个月的存储过程仍然很满意,没有出现错误。

I am looking for suggestions on how to debug this or what to look for. 我正在寻找有关如何调试或查找内容的建议。 Particularly how can it throw the error sometimes and not others? 特别是它如何有时会引发错误,而不会引发其他错误?

The code that you've posted looks fine to me. 您发布的代码对我来说很好。 Is this the complete code? 这是完整的代码吗?

The only thing that comes to mind is that your "ABC" stored procedure also has a temp table called #TMP_DATES. 唯一想到的是您的“ ABC”存储过程还具有一个称为#TMP_DATES的临时表。 The temp table in ABC would then also be available in the scope of the called stored procedure. 这样,在被调用的存储过程的范围内,ABC中的临时表也将可用。

However, if that were the case, you should get a different error when you called CREATE TABLE #TMP_DATES in the called procedure. 但是,在这种情况下,当在被调用过程中调用CREATE TABLE #TMP_DATES时,应该会得到另一个错误。

Temp tables have a scope greater than just one procedure. 临时表的作用域不仅仅是一个过程。

So you can create a temp table in uspProc1...and if in uspProc1, you call uspProc2, uspProc2 "can see" the temp table you created. 因此,您可以在uspProc1中创建一个临时表...如果在uspProc1中,您调用uspProc2,则uspProc2可以“看到”您创建的临时表。

Make sure you provide unique names to your #temp tables. 确保为#temp表提供唯一的名称。

Below is an example demonstrating the point. 以下是说明这一点的示例。

IF EXISTS 
    (
    SELECT * FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc001'  
    )
BEGIN
    DROP PROCEDURE [dbo].[uspProc001]
END


GO

CREATE Procedure dbo.uspProc001 (
@Param1 int
)
AS

BEGIN


IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
        drop table #TableOne
end


CREATE TABLE #TableOne
( 
SurrogateKey int , 
NameOf varchar(12)
)

Insert into #TableOne ( SurrogateKey , NameOf ) select 1001, 'uspProc001'

Select * from #TableOne

EXEC dbo.uspProc002 

Select * from #TableOne

IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
        drop table #TableOne
end


END


GO




IF EXISTS 
    (
    SELECT * FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc002'  
    )
BEGIN
    DROP PROCEDURE [dbo].[uspProc002]
END


GO

CREATE Procedure dbo.uspProc002 
AS

BEGIN

IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
    Insert into #TableOne ( SurrogateKey , NameOf ) select 2001, 'uspProc002'
end



END


GO










exec dbo.uspProc001 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM