CONTAINSTABLE predicate fails when invoked several times in short time - sql-server

I've got a pretty curious problem...
I have written a stored procedure with a CONTAINSTABLE predicate; something like
SELECT dbo.MyTable.MyPK
FROM dbo.MyTable INNER JOIN
CONTAINSTABLE(dbo.MyTable, FullTextField, 'mysearch') AS tbl1
ON tbl1.[KEY] = dbo.MyTable.MyPK
If I run this SP with SQL Server Management Studio, it's all ok.
Now I've prepared an automatic test suite to try the effectiveness of my work under heavy weight...
I call my SP several times, with different parameters, for a bunch of times, and here there's the problem: if I launch my test suite, it fails returning a wrong result (e.g. 1 result while I'm expecting 3 results, and so on...). But if I launch my test suite in debug mode, stepping through my test code, no errors occur. Moreover, if I catch the wrong result and try to re-execute the SP that gave the wrong result (simply placing a conditional breakpoint on the error condition and dragging the execution pointer on visual studio...), the re-execution returns the right result!!!
What can I do???
Any ideas?
Thank you very much for your help!!
Bye cghersi

Obviously running the same statement against your database should not yield different results with all else being the same. Something is changing.
Run SQLProfile while you're stepping through your code to confirm that:
The SQL you think you're sending to the database is what is actually hitting the database
No other users are updating the database while you're stepping
Make sure in your profile trace that you can identify the connection that you're using (an easy way is to alter your connection string by setting the app name). When you're stepping through your code watch the profile trace. Copy the SQL that you see there into SSMS and run it directly to confirm results. At the end of the day you should be able to isolate this to raw TSQL running in SSMS to find out where the problem is.

Related

How do I test whether a Python SQL query worked if it's not supposed to return anything?

I read an excellent post here about error handling. Error handling in Python-MySQL
And there are a thousand similar questions from people with problems where their query isn't returning anything - but that's because it's supposed to.
I have a slightly different problem.
I have a SQL Query which is designed to transform creating a new table.
SELECT *
INTO MyDataBase.MySchema.NewTable
FROM
(SELECT
ID,
Count(*) AS ProductCount
FROM
MyDataBase.MySchema.MyTable
GROUP BY
ID
) ProductCount
If I run the query in SSMS it works perfectly and SSMS simply tells me
(1901 rows affected)
Completion time: 2021-12-07T09:28:32.2541722+13:00
But after I deliberatly mis-edit the code, and try running the query from a pyhon script just gives me a vague result with no indicaton that the script didn;t actually work.
row = curs.fetchone()
pyodbc.ProgrammingError: No results. Previous SQL was not a query.
So... How do I check that the tranform, the SQL query, ran successfully, even if it's not supposed to return any results... from python?
I know it didn't.
fetchone() is to return rows if there are outputs. You don't need it in your case.
Any DDL statements you can run by just using cursor.execute('drop table..'). There is no way to know for sure if it worked actually, but if it didn't error out then it was successful. You can have additional checks to be sure based on scenario.
Also don't forget to do a cursor.commit() in the end, else it won't commit all your statements.

Stored proc failing with SQL error 3621, runs fine in ssms and if dropped and recreated

I have a stored proc that is called by a .net application and passes an xml parameter - this is then shredded and forms the WHERE section of the query.
So in my query, I look for records with a documentType matching that contained in the XML. The table contains many more records with a documentType of C than P.
The query will run fine for a number of week, regardless of if the XML contains P or C for documentType. Then it stops working for documentType C.
I can run both queries from SSMS with no errors (using profiler to capture the exact call that was made). Profiler shows that when run from the application, the documentType C query starts a statement then finishes before the statement ends, and before completing the outstanding steps of the query.
I ran another profiler session to capture all errors and warnings. All I can see is error 3621 - The statement has been terminated.
There are no other errors relating to this spid, the only other things to be picked up were warnings changing database context.
I've checked the SQL logs and extended events and can find nothing. I don't think the query relates to the data content as it runs in SSMS without problems - I've also checked the range values for other fields in the WHERE clause and nothing unusual or untoward there. I also know that if I drop and recreate the procedure (i.e. exact same code) the problem will be fixed.
Does anyone know how I can trace the error that is causing the 3261 failure? Profiling does not pick this up.
In some situations, SQL Server raises two error messages, one is the actual error message saying exactly what is happening and the other one is 3621 which says The statement has been terminated.
Sometimes the first message get lost specially when you are calling an SQL query or object from a script.
I suggest you to go through each of your SQL statement and run them individually.
Another guess is you have a timeout error on your client side. If you have Attention event on your SQL Server trace, you can follow the timeout error messages.

How do I trace database writes in SQL Server?

I'm using SQL Server 2008 R2, trying to reverse-engineer an opaque application and duplicate some of its operations, so that I can automate some massive data loads.
I figured it should be easy to do -- just go into SQL Server Profiler, start a trace, do the GUI operation, and look at the results of the trace. My problem is that the filters aren't working as I'd expect. In particular, the "Writes" column often shows "0", even on statements that are clearly making changes to the database, such as INSERT queries. This makes it impossible to set a Writes >= 1 filter, as I'd like to do.
I have verified that this is exactly what's happening by setting up an all-inclusive trace, and running the app. I have checked the table beforehand, run the operation, and checked the table afterward, and it's definitely making a change to the table. I've looked through the trace, and there's not a single line that shows any non-zero number in the "Writes" column, including the line showing the INSERT query. The query is nothing special... Just something like
exec sp_executesql
N'INSERT INTO my_table([a], [b], [c])
values(#newA, #newB, #newC)',
N'#newA int,#newB int,#newC int', #newA=1, #newB=2, #newC=3
(if there's an error in the above, it's my typo here -- the statement is definitely inserting a record in the table)
I'm sure the key to this behavior is in the description of the "Writes" column: "Number of physical disk writes performed by the server on behalf of the event." Perhaps the server is caching the write, and it happens outside of the Profiler's purvue. I don't know, and perhaps it's not important.
Is there a way to reliably find and log all statements that change the database?
Have you tried a Server Side Trace? It also works to document read and writes, which - if I'm reading you correctly - you are wanting to document writes.

How to get sql_id in OCI

Is there a way to get the sql_id/child number/plan hash after calling OCIStmtExecute()? I can't see it in OCIAttrGet().
NOTE: As a regular user who can't see v$session - if I can it's as simple as executing select prev_sql_id, prev_child_number from v$session where sid=sys_context('USERENV', 'SID')
Thanks!
There is no means to get the sql_id or the plan_hash_value with oci or sys_context. However it might be a good idea to file an enhancement request with oracle support to add that feature.
There is the possibility to trace all sql statements of a session with the following statement:
alter session set events '10046 trace name context forever, level 12'
Depending on the trace level more or less trace is generated (Level 4 and 8 create less information). To turn off the tracing execute
alter session set events '10046 trace name context off'
The other option is to create a function to compute the sql_id yourself
Use the sql text and calculate a 128bit md5
The lower 64 bit are the sql_id (and if you are interested the lower 32 bits are the plan hash)
Of course this is error prone as oracle might change the mechanism to calculate the sql_id in the future.
The following query is supposed to work but only if it is the very next statement execution following the one that you wish to identify.
select prev_sql_id, prev_child_number
from v$session
where sid = sys_context('userenv','sid')
And it does work...most of the time. My customer wrote a PL/SQL application for Oracle 12c and placed the above query in the part of the code that executes the application query. He showed me output that shows that it sometimes returns the wrong value for prev_child_number. I watched and it is indeed failing to always return the correct data. Over 99 distinct statement executions it returned the wrong prev_child_number 6 times.
I am in the process of looking for existing bugs that cause this query to return the wrong data and haven't found any yet. I may have to log a new SR with Oracle support.

Using the result of the SQL "Messages" pane

I have an existing SQL 2005 stored procedure that for some reason, outputs its results in the Messages pane in SSMS instead of the Results pane. (Its actually a CLR procedure already compiled and deployed to all our servers, and used for another daily process. So I can't change it, I just want to use its output.)
For the sake of discussion, here's a stored proc that behaves the same way:
CREATE PROCEDURE [dbo].[OutputTest]
#Param1 int, #Param2 varchar(100)
AS
BEGIN
SET NOCOUNT ON;
PRINT 'C,10000,15000';
PRINT 'D,30000,90000';
PRINT 'E,500,50000';
END
So no actual SELECT statement in there, and if you run this, you'll see these results only on the Messages pane.
Is there any way for me to use these results as part of a larger query? Put them in a temp table or something, so I can parse them out?
None of the "normal stuff" works, because there is no true "output" here:
INSERT INTO #output
EXEC OutputTest 100, 'bob'
just shows
C,10000,15000
D,30000,90000
E,500,50000
(0 row(s) affected)
on the messages pane, and the temp table doesn't actually get anything put into it.
Can you execute the stored proc from C# code? If so, you might be able to hook into the SqlCommand event called SqlInfoMessage:
SqlConnection _con = new SqlConnection("server=.;
database=Northwind;integrated Security=SSPI;");
_con.InfoMessage += new SqlInfoMessageEventHandler(_con_InfoMessage);
The event handler will look like this:
static void _con_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
string myMsg = e.Message;
}
The "e.Message" is the message printed out to the message window in SQL Server Mgmt Studio.
While it won't be pretty and might require some ugly parsing code, at least you could get a hold of those messages that way, I hope!
Marc
You cannot trap, catch or use these messages from within SQL Server. You can, however, receive them from within a client application.
I don't think there is a way but even if there is I think you should seriously consider whether it is a good idea. This sounds like a fudge which can only cause you pain in the long term. Creating an alternative proc that does exactly what you want sounds to me like a better plan.
there is no way to get messages from the message pane in your result.
if you think about it the SSMS is just a client that parses those messages the way you see it.
if you wan to use them in your app take a look at Connection Events in ADO.NET
The only way I could think that this might be possible is if the output is printed via the RAISERROR command. In that case, you might be able to capture it elsewhere using TRY/CATCH.
But that's just an idea: I've never done it. In fact, the only thing we do that's remotely close is that we have a command line tool to run stored procedures in batch jobs rather than using sql server agent to schedule them. This way all of our nightly jobs are scheduled in one place (the windows task scheduler) rather than two, and the command line tool captures the anything printed to the message window into a common logging system that we monitor. So some of procedures will output quite a lot of detail to that window.

Resources