In a stored procedure on an SQL Server 2008 database, I've added an OPENQUERY in the FROM clause of a SELECT statement, and that in turn contains an OPENQUERY, something like this:
SELECT MyField
FROM OPENQUERY (LinkedServer,
'select MyField
from OPENQUERY (OtherServer,
''select t.SomeField as [MyField]
from table t'');
Now, I wonder what happens if either one of these servers is down for some reason. Does it just return an empty result set or does it throw an error? Also, if OtherServer is down, do I need to handle the error in the outer OPENQUERY?
It is important that everything is handled within the sproc, i.e. no error should be propagated to the caller of the sproc.
The MSDN documentation on OPENQUERY does not detail any behaviour in case the linked servers are unavailable.
I found this answer on DBA.SE that mentions the sp_testlinkedserver sproc. Is calling this the way to go? How would I use it to test OtherServer?
We've tested it by changing credentials for OtherServer so that the inner OPENQUERY fails. An exception occurs:
Cannot initialize the data source object of OLE DB provider "MSDASQL" for linked server "OtherServer".
OLE DB provider "MSDASQL" for linked server "OtherServer" returned message "[MySQL][ODBC 5.3(a) Driver]Access denied for user '[user]' (using password: YES)".
And it is propagated to the stored procedure. Thus, surrounding the query in a TRY...CATCH block should provide correct means for error handling.
Related
We recently moved a database to it's own SQL Server which broke a call to a stored proc wrapped in a sp_cursoropen statement.
The original call, which worked, was to a database on the same server as the calling database:
using database1
exec sp_cursoropen #p1 output, N'exec database2.dbo.sp_mystoredproc 1234'
We had to move the second database to its own server for compliance reasons and created a linked server between the two. We changed the call to:
using database1
exec sp_cursoropen #p1 output, N'exec LinkedDBServer.database2.dbo.sp_mystoredproc 1234'
The call no longer works and gives us two errors
A server cursor cannot be opened on the given statement or statements. Use a default result set or client cursor.
The cursor was not declared
The funny thing is that running the stored proc command on it's own works and returns rows of data:
using database1
exec LinkedDBServer1.database2.dbo.sp_mystoredproc 1234
Also funny, putting direct SQL from the stored proc itself and pasting it in place of sp_mystoredproc also works, even with the cursor:
using database1
exec sp_cursoropen #p1 output, N'Select * from LinkedDBServer1.Dbname.dbo.sometable where sometable.id = 1234'
This leads me to believe that the return type of the stored procedure that runs via a linked server is somehow different than that of the same stored procedure running on the same SQL server as the calling database. Unfortunately, I cannot find any documentation to support my hypothesis.
Does anyone know why a stored procedure that returns rows of data wouldn't play well with sp_cursoropen when a linked server is involved?
Note: I'm not interested in workarounds. I know there are many ways to fix this such as writing to a temp table first, using a different service to grab the data or some other method of completing the task. I'm only interested in what low level difference in the SQL server is causing this error even though the separate pieces being called to through the linked server work independently.
I'm trying to execute an SQL Server stored procedure using the execute SQL task of an SSIS package and I'm getting errors.
CLI0115E Invalid cursor state. SQLSTATE=24000
Cannot fetch a row from OLE DB provider "xxx.xxx" for linked
server "xxxxx".". Possible failure reasons: Problems with the query,
"ResultSet" property not set correctly, parameters not set correctly,
or connection not established correctly.
The stored procedure inserts data to a temp table and it contains a query with a join to db2 server. I'm using OPENQUERY to connect to the db2 database.
Example:
select column1, column2, column3 from OPENQUERY(#databasename,'select col1, col2, col3 from db2table1 where col3=xx') as qry1
join sqltable1 on qr1.col1 = sqltable1=col1
The SSIS package is supposed to run in loops and each time the stored procedure is supposed to return nearly 500 records. The error happens intermittently and doesn't occur when the stored procedure is run manually using SQL Server Management studio.
Any help would be much appreciated.
I am migrating several hundred stored procedures from one server to another, so I wanted to write a stored procedure to execute an SP on each server and compare the output for differences.
In order to do this, I would normally use this syntax to get the results into tables:
select * into #tmp1 from OpenQuery(LocalServer,'exec usp_MyStoredProcedure')
select * into #tmp2 from OpenQuery(RemoteServer,'exec usp_MyStoredProcedure')
I then would union them and do a count, to get how many rows differ in the results:
select * into #tmp3
from ((select * from #tmp1) union (select * from #tmp2))
select count(*) from #tmp1
select count(*) from #tmp3
However, in this case, my stored procedure contains an OpenQuery, so when I try to put the exec into an OpenQuery, the query fails with the error:
The operation could not be performed because OLE DB provider "SQLNCLI"
for linked server "RemoteServer" was unable to begin a distributed transaction.
Are there any good workarounds to this? Or does anybody have any clever ideas for things I could do to make this process go more quickly? Because right now, it seems that I would have to run the SP on each server, script the results into tmp tables, then do the compare. That seems like a poor solution!
Thank you for taking the time to read this, and any help would be appreciated greatly!
I think your method would work - you just need to start the MSDTC. This behavior occurs if the Distributed Transaction Coordinator (DTS) service is disabled or if network DTC access is disabled. By default, network DTC access is disabled in Windows. When running and configured properly, the OLE DB provider would be able start the distributed transaction.
Check out this for instructions- it applies to any Windows Server 2003 or 2008.
Similar to your question.
Insert results of a stored procedure into a temporary table
I'm running sql server 2008 and I'm trying to run the query
OPEN CUR_InvHeader
FETCH NEXT FROM CUR_InvHeader INTO
#CH_iBilling_Log_RecID
WHILE (##FETCH_STATUS = 0) BEGIN --Loop for Cur_InvHeader
select * into tarInvoiceDetail_201101 FROM OPENROWSET('SQLNCLI', 'Server=(local);Trusted_Connection=yes;',
'EXEC _sp_cwm5_GetInvoiceDetail #CH_iBilling_Log_RecID')
I get the error
OLE DB provider "SQLNCLI10" for linked
server "(null)" returned message
"Deferred prepare could not be
completed.".
I've run sp_configure 'ad hoc..', 1
reconfigure with override
to ensure i can run the select against the openrecordset
any ideas what i might be doing wrong?
thanks in advance
The first thing that's wrong is that your "EXEC _sp_cwm5_GetInvoiceDetail #CH_iBilling_Log_RecID" statement will be evaluated as a constant, rather than pass the value of #CH_iBilling_Log_RecID through to OPENROWSET. You'd have to replace the whole "SELECT * INTO..." into a string variable and run sp_executesql on it.
The second thing wrong is that your "select into" statement will create tarInvoiceDetail_201101 every time, as INTO creates a new table when run. So if your cursor covers more than one row you'll get an error on the second pass.
Also, what does "Server=(local)" represent here? Are you trying to use OPENROWSET against your local copy of SQL Server while connected to a remote server? Or are you trying to use OPENROWSET to get around the limitation that you can't directly use a stored procedure as the source for an INSERT?
I need a little help figuring this out because I'm new to stored procedures. I am trying to import a .DBF table into Sql Server 2008 using this store procedure.
CREATE PROCEDURE spImportDB
-- Add the parameters for the stored procedure here
AS
BEGIN
-- Insert statements for procedure here
SELECT * into Products
FROM OPENROWSET('vfpoledb','C:\Users\Admin\Doc\Data\DBF',
'SELECT * FROM MyTable')
END
GO
I receive this error.
The OLE DB provider "vfpoledb" has not been registered.This isn't true, I've installed it and it works fine in my other application.
I've also tried running it this way with this provider but I receive this error message
Cannot initialize the data source object of OLE DB provider "Microsoft.Jet.OLEDB.4.0" for linked server "(null)".
CREATE PROCEDURE spImportDB
-- Add the parameters for the stored procedure here
AS
BEGIN
-- Insert statements for procedure here
SELECT * into Products
FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0','C:\Users\Admin\Doc\Data\DBF',
'SELECT * FROM MyTable')
END
GO
What's the easiest way to create this stored procedure? I want it to be a stored procedure not a wizard or program so please don't give me any programs.
You can try
SELECT * into SomeTable
FROM OPENROWSET('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver;
SourceDB=\\SomeServer\SomePath\;
SourceType=DBF',
'SELECT * FROM SomeDBF')
from this previous question
I'm not sure about the "friendly-name" for VFPOLEDB, but the second SP should work (i.e. using 'Microsoft.Jet.OLEDB.4.0') as long as you're pointing to a specific DBF file by name. It looks like you're pointing to a directory, not the actual file.
Further information may be found in:
http://msdn.microsoft.com/en-us/library/ms190312.aspx
For anyone else looking for an answer to this, the cause of this error is installing the Foxpro driver for "Just Me" instead of "Everyone".
Run the installer for "Everyone" to avoid this error.