On my esql program when an sql fails and generates the exception I want to print the SQL that generated the exception. For that I need to find out how to get the previously executed SQL. I am running informix 11.5.
I tried the following but nothing works
select * from sysmaster:sysconblock where cbl_sessionid in (select dbinfo('SessionId') from sysmaster:syssqlstat);
SELECT scs_sqlstatement FROM sysmaster:syssqlcurses WHERE scs_sessionid in (select dbinfo('SessionId') from sysmaster:syssqlstat);
All these get the sql of it self. For example if I run select * from sysmaster:sysconblock it show "select * from sysmaster:sysconblock" in the last executed. Is there any way to get this in informix? and is it [possible to do it on ESQL program?
Many Thanks
You're on the right track, but if you're using the same connection to run those SQL statements, then of course their successful execution obliterates the information from the previous statement. (In fact it's almost a perfect example of a heisenbug.)
What you need to do is create a second connection to the database, and use that to interrogate sysmaster content for the main connection that failed.
Connect to database for main program processing.
Identify SessionID and capture to a variable.
Connect to sysmaster database with a fresh connection.
Start processing on main connection.
When main connection processing fails with an error, use secondary connection with SessionID as parameter to obtain SQL etc.
Hope that's helpful.
Related
I'm trying to see if there is data in a stream and I provided the exact stream name as follows :
Select SYSTEM$STREAM_HAS_DATA('STRM_EXACT_STREAM_NAME_GIVEN');
But, I get an error :
SQL compilation error: Invalid value ['STRM_EXACT_STREAM_NAME_GIVEN'] for function 'SYSTEM$STREAM_HAS_DATA', parameter 1: must be a valid stream name
1) Any idea why ? How can this error be resolved ?
2) Would it hurt to resume a set of tasks (alter task resume;) without knowing if the corresponding stream has data in it or not? I blv if there is (delta) data in the stream, the task will load it, if not, the task won't do anything.
3) Any idea how to modify / update a stream that shows up as 'STALE' ? - or should just loading fresh data into the table associated with the stream should set the stream as 'NOT STALE' i.e. stale = false ? what if loading the associated table does not update the state of the task? (and that is what is happening currently in my case, as things appear.
1) It doesn't look like you have a stream by that name. Try running SHOW STREAMS; to see what streams you have active in the database/schema that you are currently using.
2) If your task has a WHEN clause that validates against the SYSTEM$STREAM_HAS_DATA result, then resuming a task and letting it run on schedule only hits against your global services layer (no warehouse credits), so there is no harm there.
3) STALE means that the stream data wasn't used by a DML statement in a long time (I think its 14 days by default or if data retention is longer than 14 days, then it's the longer of those). Loading more data into the stream table doesn't help that. Running a DML statement will, but since the stream is stale, doing so may have bad consequences. Streams are meant to be used for frequent DML, so not running DML against a stream for longer than 14 days is very uncommon.
I am sure that I'm overlooking some simple thing here.
With a FireDac connection, if I use a SQL query with a WHERE clause that, due to the content of the search parameter, would normally return an empty result set, the OPEN command returns an error instead "Cannot open / define command, which does not return result sets". Is this by design ? Every other Delphi DB connection tool I have used simply returns an empty result set with a record count of 0.
******************************* April 16
I believe Victoria is on the right track. I had never used Firedac before so assumed it was the behaviour as designed. However if I communicate with the same RDBMS using the MS SQL driver, I do not see this happen, so I suspect it is on the Datasnap end.
I am trying to use Macros in FireDAC to Preprocess my SQL Queries. I have a TADQuery object on a Data Module with the SQL set to something like:
Select * from MyTable
join OtherTable on MyTable.Key = OtherTable.Key
&Where
Then in my code I do this:
WhereClause = 'stuff based on my form';
Query.MacroByName('Where').AsRaw := WhereClause;
Query.Open;
This has worked great for complicated queries because it lets me make sure my fields and join conditions are correct using the SQL Property editor.
My problem is when the SQL statements ends up invalid because of my where clause. Is there any way to see the SQL after pre-processing that is going to be executed? Right now I am catching the FireDac errors and showing the SQL that is on EADDBEngineException object. However that is still showing my original SQL with the macros. If I can't get to it after the error happens is there anyway to force the Macro replacement to take place so I can look at the SQL in the debugger to help me see what is wrong.
If it matters I am connecting to a MS Access database with the goal of moving to SQL Server in the near future.
Apart from using Text property, to monitor what SQL is actually going to the database engine, consider using the "FDMonitor" FireDAC utility. According to the DokWiki pages (below):
drop a TFDMoniRemoteClientLink component on your form,
Set its Tracing property to True,
Add the MonitorBy=Xxx connection definition parameter to your existing FDConnection component. You can do this in the IDE object inspector, by selecting your FDConnection component, expanding the Params property, and setting MonitorBy to mbRemote.
Note that the TFDMoniXxxxClientLink should come before TFDConnection in the data module or form creation order, so adjust this by right clicking on the form or data module, then Creation Order, and moving the TFDMoni.. component above the FDConnection.
Also, it's helpful in the options of the TFDMoniXxxxClientLink, to disable most of the events being recorded, otherwise all the data returned is also shown in the FireDAC monitor. Expand the EventKinds property, and turn all the event kinds off, except for perhaps ekConnConnect, ekConnPrepare, and ekCmdExecute.
Then open the FireDAC Monitor from the IDE, (Tools > FireDAC Monitor). Start your app only once the monitor is running. Double click on a trace event (in the Trace Output tab), and you will see the actual SQL sent to the database in the bottom pane.
It also seems likely that adding the EventType of ekConnPrepare as mentioned above, would show you when the query's Prepare is called, but I haven't played enough with it say for sure.
Please see the following pages on the DocWiki for more information:
Overview: FDMonitor
How to: Tracing and Monitoring (FireDAC)
Other FireDAC utilities: Utilities (FireDAC)
(Just to remove this question from list of unanswered questions)
From comments:
Well, I've roughly checked what's happening there and I'm still not
sure if calling Prepare (which is useless for you as I get) is the
minimal requirement to trigger that preprocessing. Though, the
preprocessed SQL, the one which is sent to the DBMS you can access
through the Text property (quite uncommon name for such property). – TLama Feb
21 '14 at 8:18
I have a very large block of SQL that I am trying to execute inside of Delphi, against a Microsoft SQL Database. I am getting this:
Multiple-step OLE DB operation generated errors.
Check each OLE DB status value, if available. No work was done.
The script has multiple sql IF statements followed by BEGIN and END blocks with invocations of stored procedures, declaration of variables, and EXEC inside that. Finally it returns some of the variable values by SELECT #Variable1 AsName1,#Variable2 AsName2....
The above multi-step error is coming in as an OLEException from ADO, not from the Delphi code, and happens after all the SQL exec-stored-procedure have occurred, and therefore I suspect it's firing this OLE exception when it reaches the final stage which SELECT #Variable1 AsName1,... to get back a few variable values for my program to see them.
I know about this retired/deprecated MS KB article, and this is unfortunately not my actual issue:
http://support.microsoft.com/kb/269495
In short that KB article says to fix a registry key and remove "Persist Security Info" from the connection string. That's not my problem. I'm asking this question because I found the answer already and I think that someone else who gets stuck here might not want to waste several hours finding potential issues when there are several that I have found after searching for solutions for several hours. Anyone who wants to add another answer with different options, is fine, and I'll select yours if it's reproducible, and if necessary I'll turn this one into a Community Wiki because there could be a dozen obscure causes for this "ADO recordset is in a bad mood and is unhappy with your T-SQL" exception.
I have found several potential causes that are listed in various sources of documentation. The original KB article in the question suggests removing the 'Persist Security Info' from my ADO connection string, however in a standalone test in an application with just a TADOConnection and a single TADOQuery, the presence or absence of Persist Security Info had no effect, nor did explicitly setting it True or False.
What DID fix it was removing this CursorType declaration:
CursorType=ctKeyset
What I have learned is that bidirectional ADO datasets are fine for SELECT * FROM TABLE in ADO but are not so fine for complex SQL scripts.
Potential source of this error is updating char field with large value.
Example: Form has edit box with max length property set to 20 characters and Oracle database table has field defined as char(10).
Updating with 10 characters (or less) will work fine while updating with more then 10 characters will cause 'Multiple step...' error on ADOQuerry.UpdateBatch().
You also have to know that CHAR will allways have 20 characters. Consider Trimming value in edit box. CHAR behaves different than VARCHAR2 type.
If you have a query with parameter ,check the number of parameters in the query is matched with script...!
I would like to create a generic logging solution for my stored procedures, allowing me to log the values of input parameters. Currently I am doing this more or less by hand and I am very unhappy with this approach. Ideally, I would like to say something like the following:
"given my spid, what are my input parameters and their values?"
This is the same information exposed to me when I run SQL Profiler -- the stored procedure's name, all input params and all input VALUES are listed for me. How can I get my hands on these values from within a stored procedure?
Thanks;
Duncan
That is going to be difficult to do within a stored procedure. SQL profiler runs under a different SPID and runs a statement like this to capture the other users statements:
DECLARE #handle VARBINARY(64)
SELECT #handle = sql_handle from sys.sysprocesses where spid = #SPID
SELECT text FROM sys.dm_exec_sql_text(#handle)
The problem is if you run this in a stored proc for the current SPID all your going to get back is the statement above. I don't believe SQL server provides a T-SQL construct to execute a batch under a different SPID. I suppose you could write a .Net dll stored procedure that executes a batch on a different connection. to do that sort of thing but it may be more trouble than it's worth.