Reputation: 575
I'm having some issues with a stored procedure I've written in my SQL2000 database to query an Oracle database via OpenQuery().
The procedure 1) creates a cursor from a table (Job) on my SQL2000 database, 2) then iterates through that cursor one at a time, passing the cursor value (JobID) to a OpenQuery(). 3) for each JobID in the Job table, it will execute the OpenQuery to query the Oracle database to get data for that JobID. 4)The returned data from each OpenQuery execution is inserted into a table called Part in my SQL2000 database.
The query works for a while, then consistently fails after running successfully for a few thousand JobID's. It returns this error:
Server: Msg 7321, Level 16, State 2, Line 1 An error occurred while preparing a query for execution against OLE DB provider 'MSDAORA'. OLE DB error trace [OLE/DB Provider 'MSDAORA' ICommandPrepare::Prepare returned 0x800706be].
Any idea what I could be doing wrong? On my most recent run, it ran successfully for 16,186 loops through the cursor before failing. The JobID that failed was only 1 integer larger than the previous JobID that was successful and it didn't return a much larger query result either, only one more row.
--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
Upvotes: 0
Views: 996
Reputation: 70513
I've an idea, why not just get rid of the cursor and all the dynamic stuff.
I would try something like this:
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
Now you don't have to make "1000s" of connections -- just one. I imagine you won't have as many errors.
As a side benefit you get something that will run 1000s of times faster.
Update based on comment below
Given that the Oracle table has millions of records and you only want 10 of thousands of records I would try this (I'm guessing you are only looking at a sub-set jobs and this is reflected in the id ordering -- I'm sure there is a better way to do this if I knew more about your schema.)
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
Update based on comment 2 below
I have some ideas but I don't know for sure. I've seen something like this in the ASP.NET connection pool. When I had that problem it was because connections were not being cleared correctly when they had an error. It would retry the connection and succeed on a connection, but the bad connection would be put back in the pool. Then when it got used again it would fail. It might be something like that.
Since it is not hard to try, I recommend trying the JobID range. See what happens. Or if there is some other criteria you can use to limit selecting all the rows you need (eg date) use that. I think one request is much better than many and I expect it will use much less time in total than the multiple queries.
Upvotes: 3