T-SQL存储过程失败,消息为消息Msg 7321

时间:2010-11-09 19:35:18

标签: sql-server tsql sql-server-2000

我在SQL2000数据库中编写的存储过程存在一些问题,通过OpenQuery()查询Oracle数据库。

程序 1)从我的SQL2000数据库上的表(Job)创建一个游标, 2)然后一次迭代该游标,将游标值(JobID)传递给OpenQuery()。 3)对于Job表中的每个JobID,它将执行OpenQuery以查询Oracle数据库以获取该JobID的数据。 4)每个OpenQuery执行的返回数据都插入到我的SQL2000数据库中名为Part的表中。

查询工作了一段时间,然后在成功运行几千个JobID之后一直失败。它返回此错误:

服务器:消息7321,级别16,状态2,行1 准备查询以对OLE DB提供程序“MSDAORA”执行时发生错误。 OLE DB错误跟踪[OLE / DB提供程序'MSDAORA'ICommandPrepare ::准备返回0x800706be]。

知道我可能做错了吗?在我最近的运行中,它在失败之前通过游标成功运行了16,186个循环。失败的JobID只比前一个成功的JobID大1个整数,它也没有返回更大的查询结果,只有一行。

--DECLARE Variables
DECLARE @JobID      int
DECLARE @OpenQuerySQL       varchar(6000)
DECLARE @INSERTSQL          varchar(500)
DECLARE @Count              int


--INSERT SQL stays static 
--PRINT 'SET @INSERTSQL' 
SET @Count = 0
SET @INSERTSQL = 'INSERT INTO [Part]
           ([JobID]
           ,[PartID]'

    BEGIN

        --Declare cursor
        DECLARE JobCursor CURSOR FOR
            SELECT DISTINCT JobID
            FROM Job
            ORDER BY JobID

        --Open the cursor and get first Job for Program
        OPEN JobCursor
        FETCH NEXT FROM JobCursor
            INTO @JobID

        WHILE @@FETCH_STATUS = 0
            BEGIN
                SET @Count = @Count + 1
                SET @OpenQuerySQL = 'SELECT * FROM OpenQuery(linkedserver, ''' + 
                                    'SELECT DISTINCT JobID, PartID
                                     FROM OraclePartTable
                                    WHERE JobID = ' + CAST(@JobID AS varchar(20)) + ''')'

                    PRINT CAST(@Count AS varchar(9)) + ') JobID = ' + CAST(@JobID AS varchar(13))
                    PRINT @OpenQuerySQL
                    EXEC (@INSERTSQL + @OpenQuerySQL)
                    FETCH NEXT FROM JobCursor
                    INTO @JobID
                END


        CLOSE JobCursor
        DEALLOCATE JobCursor
    END

1 个答案:

答案 0 :(得分:3)

我有一个想法,为什么不摆脱光标和所有动态的东西。

我会尝试这样的事情:

INSERT INTO [Part]  ([JobID],[PartID])
   SELECT oResults.JobID, oResults.PartID 
   FROM OpenQuery(linkedserver, 'SELECT DISTINCT JobID, PartID FROM OraclePartTable') as oResults
   INNER JOIN Job J ON oResults.JobID = J.JobID

现在你不必制作“1000s”的连接 - 只需一个。我想你不会有那么多的错误。

作为一个附带好处,你可以获得快1000倍的东西。


根据以下评论进行更新

鉴于Oracle表有数百万条记录,你只想要成千上万的记录,我会尝试这个(我猜你只是在查看一个子集作业,这反映在id排序中 - 如果我对您的架构有更多了解,我相信有更好的方法可以做到这一点。)

DECLARE @maxID int
DECLARE @minID int

SELECT @maxID = max(JobID), @minID = min(JobID) FROM Job

INSERT INTO [Part]  ([JobID],[PartID])
   SELECT oResults.JobID, oResults.PartID 
   FROM OpenQuery(linkedserver, 'SELECT DISTINCT JobID, PartID ' +
                                'FROM OraclePartTable ' +
                                'WHERE JobID <= '+cast(@maxID as varchar(20)+
                                ' AND JobID >= '+case(@minID as varchar(20)) as oResults
   INNER JOIN Job J ON oResults.JobID = J.JobID

根据以下评论2进行更新

我有一些想法,但我不确定。我在ASP.NET连接池中看到过类似的东西。当我遇到这个问题时,原因是当他们遇到错误时没有正确清除连接。它将重试连接并在连接上成功,但错误的连接将被放回池中。然后再次使用它会失败。它可能是那样的。

由于不难尝试,我建议尝试JobID范围。走着瞧吧。或者,如果存在其他一些标准,您可以使用它来限制选择所需的所有行(例如日期)。我认为一个请求比许多请求要好得多,我希望它总共会比多个查询使用更少的时间。