我在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
答案 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范围。走着瞧吧。或者,如果存在其他一些标准,您可以使用它来限制选择所需的所有行(例如日期)。我认为一个请求比许多请求要好得多,我希望它总共会比多个查询使用更少的时间。