Query to Linked Server never stops executing - sql-server-2005

I have created a linked server in SQL Server 2005 to an Oracle DB. When I run a query, The query never stops executing, and never returns results. When I cancel the query, it never completes cancelling. I have to close the window to get it to stop.
I have set things up as follows:
Installed Oracle Client Tools on SQL Server
Ran following query:
EXEC sp_addlinkedserver
#server = 'MyNewLinkedServer',
#srvproduct = 'Oracle',
#provider = 'OraOLEDB.Oracle',
#datasrc = 'TNSNAMES_Entry'
I then added the TNSNAMES.ORA file to ORAHOME1\network\admin\ directory.
In Properties for my Linked Server, I changed the Security settings to Be made using this security context: for all connections using my Oracle username/password
I ran the following query:
SELECT * FROM OPENQUERY(MyNewLinkedServer, 'SELECT COUNT(*) FROM MySchema.MyTable');
The query never completes execution. Anyone have any insights? Any steps I'm missing?
UPDATE:
I came in the following day and tried the query again and it worked just fine. I suspect network issues of some sort.

Look on the Oracle server, querying v$session. See if you can see the remote connection, and what the Oracle session is doing. You can even do a trace on the Oracle side (set off by a login trigger) to record everything that happens (eg parse of query, returned errors etc).

Related

SQL Server stored procedure no statements run when from RPC

I have a SQL Server 2000 database with a stored procedure that deletes a row from a specific table, given its id. When I call the stored procedure from VB.NET, it does not delete the row, but running the same script directly on the database via SSMS, it works.
Here's my chain of events:
Start SQL Server Profiler to watch all calls to the database. I have
it setup to track when stored procedure starts, completes, and even
on SQL statements start/complete within that stored procedure.
Call stored procedure via VB.NET dll.
Stop the profiler trace to avoid excessive data to dig through.
Select from table, and see that the row still exists.
View the profiler trace, which only shows RPC:Starting, SP:Starting, RPC:Completed. No inner statements are traced, which verifies why the row wasn't deleted since the delete statement never fired.
Copy/paste the EXEC call directly from the RPC:Starting trace entry from when it was called via VB.NET, into SQL Server Management Studio query window pointed to the same database with same credentials.
Start profiler again.
Execute EXEC statement from bullet 6 in SSMS.
Stop profiler.
Select from table, and see that the row GOT DELETED like it should.
View the profiler trace, which shows SP:Starting, all statements starting/completed including the DELETE statement, and SP:Completed.
Why would running it via RPC make it not execute any of the statements in the proc, but running directly acts as it should?
EDIT: Below is my VB.NET code. This is the same code we use in over 100 other places:
Dim paramRowID As New SqlParameter("#RowID", sRowID)
Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(oConn, "spDeleteRow", paramRowID)
See SqlHelper source here.
EDIT: I hate myself right now. :) SQL threw an exception "nvarchar is incompatible with image" about another parameter that I was passing NULL to. SSMS didn't worry about the type, but VB.NET did since I didn't explicitly tell it that it was of type image. Once I defined that param, it worked. I wish profiler would have told me there was an error though.
Any help would be appreciated,
Greg
That would be because SSMS does not call an RPC but a batch. There is no way in fact to call a RPC from SSMS since you cannot declare a parameter, which is what differentiate an RPC call from a batch call in TDS:
2.2.1.3 SQL Batch To send a SQL statement or a batch of SQL statements, the SQL batch, represented by a Unicode string, is copied into the data section of a TDS packet and then sent to the database server that supports SQL. A SQL batch may span more than one TDS packet. See section 2.2.6.6 for additional detail
2.2.1.5 Remote Procedure Call To execute a remote procedure call (RPC) on the server, the client sends an RPC message data stream to the server. This is a binary stream that contains the RPC name or numeric identifier, options, and parameters. RPCs MUST be in a separate TDS message and not intermixed with SQL statements. There can be several RPCs in one message. See section 2.2.6.5 for additional details.
So monitor instead for the SQL:BatchCompleted event and you'll see your SSMS statement(s).
Does the user the application is using to connect to sql have permission to execute stored procedures? That is the first thing I would verify.

SQL Server Query log for failed/incorrect queries?

I am using SQL Server 2008 and I would like to know if there's a way to find invalid SQL queries that have been executed in a database. For example:
SELECT * FROM NonExistingTable
...where the database didn't exist or a SELECT/INSERT/UPDATE with incorrect syntax.
SQL Server doesn't keep a log of these things, so if you want to capture them you'll have to do so using a server-side trace with a filter to only capture statements with errors. It will be quite an expensive trace, and you'll get some false positives if you do things like RAISERROR WITH NOWAIT... I guess it's easier than implementing TRY/CATCH everywhere and logging the errors yourself?
There may be ways to do it with SQL Server Audit (depending on your edition)
or Extended Events but I haven't tried to do this specific thing with either...
Logging of the message 229 severity 14 would definitely help you identify when these errors take place.
SELECT * FROM master.sys.messages
WHERE language_id=1033
AND severity=14
AND message_id=229;
You can enable it by using:
EXEC sp_altermessage 229, 'WITH_LOG', 'true';
I'd create an alert on Severity 14 errors to be notified when they happen, for that you'd need to set an operator too.
The only limitation that this has is that it does not give you the login, host name or IP address of the session that had the error. It does log the SPID and you'd have to retrieve it by using EXEC xp_readerrorlog by using something like
EXEC xp_readerrorlog 0,1,'permission',NULL,NULL,NULL,'desc'
or opening it on SSMS and then correlate it with what you find on sysprocesses using
SELECT * FROM master.dbo.sysprocesses WHERE SPID='LoggedSPID'
You can enable the logging of other messages you may want to be aware of, for this purpose, primarily dig on severity 14 and enable as needed.
SELECT * FROM master.sys.messages
WHERE language_id=1033
AND severity=14;

Simplest SQL query never returns

I have a SQL query that is quite simply select * from tblOrders where customerID = 5000but it never returns. I waited 10 minutes and gave up.
The weirdest thing is that other queries on the same DB, but on another table, works fine. Removing the where-clause doesn't help either, so it seems like the table is somehow not responding. It's about 30000 lines, so it's not the biggest table either.
I'm using MS SQL SMS 2008 Express against a SQL Server 2008 express running on a remote server.
Try this to by-pass any locks on table -
select * from tblOrders(nolock) where customerID = 5000
It sounds like your table is locked
run this query to see what locks are held against it.
USE master;
GO
EXEC sp_lock;
GO
but table locking is a whole mindfield of its own
here is some info in the sp_lock system stored proc
http://msdn.microsoft.com/en-us/library/ms187749.aspx
when you find the lock you can kill it
KILL { session ID | UOW } [ WITH STATUSONLY ]
http://msdn.microsoft.com/en-us/library/ms173730.aspx
I agree with the others that this is most probably a locking issue. By default write access to a table still blocks read (only) access.
Since SQL Server 2005 this can be fixed by using the "row versioning". You need to change the settings of the database to enable this.
See the manual for a more detailed explanation:
http://msdn.microsoft.com/en-us/library/ms345124%28SQL.90%29.aspx

How to run a stored procedure every day in SQL Server Express Edition?

How is it possible to run a stored procedure at a particular time every day in SQL Server Express Edition?
Notes:
This is needed to truncate an audit table
An alternative would be to modify the insert query but this is probably less efficient
SQL Server Express Edition does not have the SQL Server Agent
Related Questions:
How can I schedule a daily backup with SQl Server Express?
Scheduled run of stored procedure on SQL Server
Since SQL Server express does not come with SQL Agent, you can use the Windows scheduler to run a SQLCMD with a stored proc or a SQL script.
http://msdn.microsoft.com/en-us/library/ms162773.aspx
I found the following mechanism worked for me.
USE Master
GO
IF EXISTS( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[MyBackgroundTask]')
AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[MyBackgroundTask]
GO
CREATE PROCEDURE MyBackgroundTask
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- The interval between cleanup attempts
declare #timeToRun nvarchar(50)
set #timeToRun = '03:33:33'
while 1 = 1
begin
waitfor time #timeToRun
begin
execute [MyDatabaseName].[dbo].[MyDatabaseStoredProcedure];
end
end
END
GO
-- Run the procedure when the master database starts.
sp_procoption #ProcName = 'MyBackgroundTask',
#OptionName = 'startup',
#OptionValue = 'on'
GO
Some notes:
It is worth writing an audit entry somewhere so that you can see that the query actually ran.
The server needs rebooting once to ensure that the script runs the first time.
Create a scheduled task that calls "C:\YourDirNameHere\TaskScript.vbs" on startup. VBScript should perform repeated task execution (in this example, it's a 15 minute loop)
Via command line (must run cmd.exe as administrator):
schtasks.exe /create /tn "TaskNameHere" /tr "\"C:\YourDirNameHere\TaskScript.vbs\" " /sc ONSTARTUP
Example TaskScript.vbs: This executes your custom SQL script silently using RunSQLScript.bat
Do While 1
WScript.Sleep(60000*15)
Set WshShell = CreateObject("WScript.Shell")
WshShell.RUN "cmd /c C:\YourDirNameHere\RunSQLScript.bat C:\YourDirNameHere\Some_TSQL_Script.sql", 0
Loop
RunSQLScript.bat: This uses sqlcmd to call the database instance and execute the SQL script
#echo off
sqlcmd -S .\SQLEXPRESS -i %1
If you are using Express Edition, you will need to use the Windows Scheduler or the application connecting to the server in some way.
You would use the scheduler to run sqlcmd. Here are some instructions for getting the sqlcmd working with express edition.
SQL Scheduler from http://www.lazycoding.com/products.aspx
Free and simple
Supports all versions of SQL Server 2000, 2005, and 2008
Supports unlimited SQL Server instances with an unlimited number of jobs.
Allows to easily schedule SQL Server maintenance tasks: backups, index rebuilds, integrity checks, etc.
Runs as Windows Service
Email notifications on job success and failure
Since another similar question was asked, and will likely be closed as a duplicate of this one, and there are many options not mentioned in the answers already present here...
Since you are using SQL Express you can't use SQL Server Agent. However there are many alternatives, all of which you can schedule using AT or Windows Task Scheduler depending on your operating system:
VBScript
C# command line app
batch file with SQLCMD
PowerShell
All of these languages/tools (and many others) have the capacity to connect to SQL Server and execute a stored procedure. You can also try these Agent replacements:
SQLScheduler
Express Agent
Standalone SQL Agent (beta)
The easiest way I have found to tackle this issue is to create a query that executes the stored procedure then save it. The query should look similar to this one below.
use [database name]
exec storedproc.sql
Then create a batch file with something similar to the code below in it.
sqlcmd -S servername\SQLExpress -i c:\expressmaint.sql
Then have the task scheduler execute the batch as often as you like
Another approach to scheduling in SQL Express is to use Service Broker Conversation Timers. To run a stored procedure periodically, which you can use to bootstrap a custom scheduler.
See eg Scheduling Jobs in SQL Server Express
You could use Task Scheduler to fire a simple console app that would execute the Sql statement.
As you have correctly noted, without the agent process, you will need something else external to the server, perhaps a service you write and install or Windows scheduler.
Note that with an Express installation for a local application, it is possible that the machine may not be on at the time you want to truncate the table (say you set it to truncate every night at midnight, but the user never has his machine on).
So your scheduled task is never run and your audit log gets out of control (this is a problem with SQL Server Agent as well, but one would assume that a real server would be running non-stop). A better strategy if this situation fits yours might be to have the application do it on demand when it detects that it has been more than X days since truncation or whatever your operation is.
Another thing to look at is if you are talking about a Web Application, there might be time when the application is loaded, and the operation could be done when that event fires.
As mentioned in the comment, there is sp_procoption - this could allow your SP to run each time the engine is started - the drawbacks with this method are that for long-running instances, there might be a long time between calls, and it still has issues if the engine is not running at the times you need the operation to be done.
Our company also use SQLEXPRESS and there is no SQL Agent.
Since there is no marked answer as "right" and all the solutions are quite complex I'll share what I did there. May be its really bad, but it worked great to me.
I've chosen operations of Insertion (people do) to a table that got closely the same time range i needed and made a trigger "ON INSERT" that applies needed function.

SQL Server: Snapshot transaction problem with synonyms in Express Edition

We have 2 databases, say DB1 and DB2.
DB1 contains all the stored procedures which access also data in DB2.
DB1 uses synonyms to access the tables in DB2.
(Using synonyms is a requirement in our situation)
This works perfectly fine in all situations with SQL Server 2005 Developer Edition.
However in the Express Edition, we get an exception when we do the following:
1 Restart SQL Server
2 Execute the following code within DB1:
set transaction isolation level snapshot
begin transaction
declare #sQuery varchar(max)
set #sQuery = 'Select * from synToSomeTableInDB2'
exec (#sQuery)
commit transaction
This will result in the following error:
Snapshot isolation transaction failed in database '...' because the database was not recovered when the current transaction was started. Retry the transaction after the database has recovered.
The same select query passes fine when used without the EXEC or when run on the Developer Edition.
Restarting the server in step 1 is important as once a connection was made to DB2, the code runs also fine on SQL Server Express Edition.
Does anyone have an idea what this is? We need to be able to use EXEC for some dynamic queries.
We've already checked MSDN, searched Google, ...
Any help is greatly appreciated.
--- Edit: March 10 09
As discussed with Ed Harper below, I've filed a bug report for this.
See https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=422150
As found out via Microsoft Connect, the problem is that by default on SQL Server Express Edition the AUTO_CLOSE option is set on true.
Changing this option to false fixes the problem.
The error message suggests that the query fails because SQL server is still recovering the database following the service restart when you execute your query.
Does the error always occur on the first attempt to run this code, regardless of the time elapsed since the service was restarted?
Can you confirm from the SQL Server log that the database is recovering correctly after the restart?