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;
Related
I have multiple select queries which I want to execute asynchronously.
How can I do this in oracle sql ?
I basically want to test something and so want to simulate workload so I don't really care about the result and I know I can do this in multiple threads but this is specific and so would prefer if I can do this entirely in sql. procedures are fine though.
NOTE: there are no update queries only select.
I read about nowait but am not sure how to use it in oracle.
I tried something like -
select * from foo with(nowait) where col1="something";
This is the error I got -
with(nowait)
*
ERROR at line 3:
ORA-00933: SQL command not properly ended
The Oracle info on NOWAIT says:
Specify NOWAIT if you want the database to return control to you immediately
if the specified table, partition, or table subpartition is already locked by
another user. In this case, the database returns a message indicating that the
table, partition, or subpartition is already locked by another user.
This will not do what you want.
Asynchronous queries are an application thing, not a SQL thing. For example I can open TOAD and open a dozen windows and run long queries in all of them and still open another window and run another query. I could open a dozen instances of SQLPLUS and do the same thing. Nothing in the query lets me do this, it's in the application.
I think you could use DBMS_SCHEDULER to schedule some sql or procs that execute SQL.
However this is probably not the best way to do this
There are tools for this. The best way maybe to write a procedure you can call from the web and then you can use any performance testing tool that can make a web call...its worked for me before.
You may also consider:
http://sqlmag.com/database-performance-tuning/testing-heavy-load-simulating-multiple-concurrent-operations
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
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).
Is there away to cause a script to prevent running if an if statement is true even with "GO"'s?
For example I want to do something similar to the following:
insert into table1 (col1, col2) value ('1', '2')
GO
if exists(select * from table1 where col1 = '1')
BEGIN
--Cause Script to fail
END
GO
insert into table1 (col1, col2) value ('1', '2') --Wont run
The actual purpose of doing this is to prevent table create scripts/inserts/deletes/updates from running more than once when we drop of packages for the DBA's to run.
GO is not a transact-sql keyword - it's actually a batch terminator understood by common SQL Server tools. If you use it in your application, your app wil fail.
Why wouldn't you do something like this?
IF NOT EXISTS (select * from table1 where col1 = '1')
BEGIN
--Do Some Stuff
END
Rather than abort the script if the condition is met, only run the script if the condition isn't met.
Alternatively, you could wrap the code in a proc and use RETURN to exit from the proc.
According to the documentation, certain values passed for the severity to RAISEERROR() can cause varying levels of termination.
The ones of most interest (if you are running a script through SQL Management Studio or similar, and want to prevent any attempt to run any subsequent commands in a the file) may be:
Severity levels from 20 through 25 are considered fatal. If a fatal severity level is encountered, the client connection is terminated after receiving the message, and the error is logged in the error and application logs.
You did not specify what tool you use to run the said script. The sqlcmd and osql tools have the -b parameter 'On error batch abort', which does exactly what you're asking. Simply replace 'cause script t fail' with a RAISERROR("failure", 16, 1).
#Jason I'd highly recommend against using error levels higher than 16 in your scripts. For one the levels above 18 require sysadmin privileges to start with. Second they may trigger all sort of automated responses from the administrative monitoring in place and even internally by the engine, including drastic measures like initiating a failover or taking the database offline. And last but not least they will cause a lot of wasted time if someone is investigating a real incident: 'a hardware failure one hour before crash, hmmm, let me look into this'.
Use goto. It sounds ugly, but works perfect for this.
Edit - nm, this doesn't work. It must have been a dream when I thought I saw it work
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?