Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 Old Forums
 CLOSED - General SQL Server
 returning rowcounts for each statement processed, as in query analyzer, in DMO applications

Author  Topic 

AskSQLTeam
Ask SQLTeam Question

0 Posts

Posted - 2002-09-11 : 14:10:09
oki writes "Hi SQLTeam,

I am new to MSSQL server (2 months junior). I am an old Oracle, Teradata dba. Now I am trying to port my Teradata datawarehouse and related applications, scripts to MSSQL 2000 server. So for 2 months, I try to collect any valuable info related for this project. Maybe I missed something but really I could' I find a sol'n and thus sent the following question to Andy. In case Andy can't receive or answer my urgent question, I also posted it here. I had modif?ed his article's script "Error handling in long-running batch jobs" for my project. In summary today I look for a way of getting rowcount etc. info through DMO. For instance:

ALTER procedure p1 as
-- SET XACT_ABORT ON
set nocount off
select 1
print '[IKS: ' + cast(@@rowcount as char(9)) + ']'
select 5 union select 4
print '[IKS: ' + cast(@@rowcount as char(9)) + ']'
go

and
some VB code:
Dim smessage As String

SQL = "exec p1"
Set odatabase = oSQLServer.Databases("production")
odatabase.ExecuteWithResultsAndMessages2 SQL, smessage
MsgBox (smessage)

returns me null smessage if I remove "print ..." lines. So I had to use prints to return that
info.


>>>>>>>>>>>>>>>
Hi Andy,

I am an old Teradata, Oracle dba, but a new MSSQL dba candidate. I am porting a Teradata datawarehouse system to MSSQL. I want to develop a monitor system to run a list of batch scripts in order. I also want to capture errors, print messages, and rowcounts of each statement. So after a search, I found your article and slightly modified it. I plan to use it giving my procedures or scripts as parameter.

Now my only problem is not to be able to log rowcounts without using "print @rowcount" after each statement in the script. I am searching for a method, option etc. to be able to log also those info as displayed by Query Analyzer tool without modifying original scripts. Besides rowcount, I would want to be informed and add any additional message, info available during script run.

Sorry for my late question. I would appreciate any comment if possible.
<<<<<<<<<<<<<<<<<<

THI
oki"

AjarnMark
SQL Slashing Gunting Master

3246 Posts

Posted - 2002-09-11 : 14:40:34
Oki,

It seems to me this would be most easily returned by using OUTPUT Parameters in your stored procedure.

ALTER procedure p1
@RowsAffect varchar(100) OUTPUT
as
-- SET XACT_ABORT ON
set nocount off
select 1
SET @RowsAffect = '[IKS: ' + cast(@@rowcount as char(9)) + ']'
select 5 union select 4
SET @RowsAffect = @RowsAffect '[IKS: ' + cast(@@rowcount as char(9)) + ']'
go

Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2002-09-11 : 15:10:44
I agree with Mark's approach, it is far easier to get that information using his method, and is more reliable too. However, if you absolutely have to have this info using DMO methods, the QueryResults object has some properties that list the number of result sets returned (the ResultSets property), and they can be enumerated using the CurrentResultSet property. The QueryResults object also has a Rows property.

Books Online has more details on these, under Contents/Building SQL Server Applications/SQL-DMO/Objects.

Go to Top of Page

oktayhg
Starting Member

2 Posts

Posted - 2002-09-12 : 02:35:20
Hi all,
Volk, Mark, thank you for your answers. First of all, I don't want to modify original code that will be executed. I used queryresults, but it seems returning only recordsets if any and corresponding rowcount. For example, an insert statement does not return any thing. Below I list my code. I look for your comments about the current one and of course my original question.

Besides, any advice about transferring, porting data/applications from Teradata/Oracle to MSSQLServer will be appreciated. For example, I suffer from 01-01-1753 minimum date restriction on MSSQL while transfers.

Thanks
OKI

Note: You can try the following code as

create procedure p1 as
-- SET XACT_ABORT ON
set nocount off
select 1
print '[IKS: ' + cast(@@rowcount as char(9)) + ']'
select 5 union select 4
print '[IKS: ' + cast(@@rowcount as char(9)) + ']'
go


declare @p varchar(550)
exec spi_BatchLog_deneme_3 'on exec p1 ', 146, null, @p out
print @p

It will return in batchlog: IKS for rowcounts, DKS for rows of queryresults if any.
 


ALTER procedure spi_BatchLog_deneme_3
@pSQL VARCHAR(8000),
@pJobID INTEGER,
@pComment VARCHAR(8000),
@pDonusAciklama VARCHAR(1000) out

-------------------------------------------------------------------------------------
-- Run the basic script
-- This could be inside a stored procedure
-------------------------------------------------------------------------------------
as

declare @rows integer

DECLARE @pDonusDegeri INTEGER
DECLARE @Status VARCHAR(255)

DECLARE @oSQLServer INTEGER
DECLARE @oDatabase INTEGER
DECLARE @oQueryResults INTEGER
DECLARE @CurrentDB VARCHAR(255)
DECLARE @Return INTEGER
DECLARE @SQL VARCHAR(8000)
DECLARE @Source VARCHAR(255)
DECLARE @Length INTEGER

DECLARE @JobID INTEGER
DECLARE @Error INTEGER
DECLARE @ErrorMsg VARCHAR(255)

SET @JobID = @pJobID
SET @pDonusDegeri = 0
SET @Status = 'BASLADI'

EXEC spi_BatchLog @JobID, Null, @pComment, @Status
BEGIN TRAN
-- Create the SQLServer object
EXEC @Error = sp_OACreate 'SQLDMO.SQLServer2', @oSQLServer OUT
IF @Error <> 0
GOTO OA_Error
-- Set the login process to use NT Authentication
EXEC @Error = sp_OASetProperty @oSQLServer, 'LoginSecure', -1
IF @Error <> 0
GOTO OA_Error
-- Connect to server using NT Authentication
EXEC @Error = sp_OAMethod @oSQLServer, 'Connect', NULL, @@SERVERNAME
IF @Error <> 0
GOTO OA_Error
-- Verify the connection
EXEC @Error = sp_OAMethod @oSQLServer, 'VerifyConnection', @Return OUTPUT
IF @Error <> 0
GOTO OA_Error
IF @Return = 0
GOTO OA_Error

-- Set the database object to be the current database
-- (We do this so we don't need to execute the SQL against the
-- SQLServer object, which would require explicit DB prefixing)
SELECT @CurrentDB = DB_NAME()
SELECT @CurrentDB = 'Databases("' + RTRIM(@CurrentDB) + '")'
EXEC @Error = sp_OAGetProperty @oSQLServer, @CurrentDB, @oDatabase OUT
IF @Error <> 0
GOTO OA_Error

-- Build the SQL string
-- SET @SQL = 'EXECUTE spi_BatchLog ' + CONVERT(CHAR(12),@JobID) + ', ' + '''Message from Inside Transaction'''+ ', ' + ''' '''
SET @SQL = @pSQL

-- Execute the SQL (this will NOT be rolled back)
-- We could use ExecuteImmediate here, but it doesn't return a result
-- and we found while debugging that you really NEED that
SET @Length = LEN(@SQL)
SET @ErrorMsg = '' -- Must initialize the @ErrorMsg string
EXEC @Error = sp_OAMethod @oDatabase, 'ExecuteWithResultsAndMessages2', @oQueryResults OUTPUT, @Command = @SQL , @Length = @Length, @Messages = @ErrorMsg OUTPUT
IF @Error <> 0
GOTO OA_Error

EXEC @Error = sp_OAGetProperty @oQueryResults, 'Rows', @Rows OUT
IF @Error <> 0
GOTO OA_Error
set @pComment = '[DKS: ' + cast(@rows as char(9)) + ']'

-- Destroy the objects
EXEC @Error = sp_OADestroy @oSQLServer
EXEC @Error = sp_OADestroy @oDatabase
EXEC @Error = sp_OADestroy @oQueryResults

GOTO DONE
-----------------------------------------------
OA_Error:
ROLLBACK TRAN
-- Get the error text
EXEC sp_OAGetErrorInfo @oSQLServer, @Source OUT, @ErrorMsg OUT
SELECT
@ErrorMsg = CONVERT(CHAR(16), @Error) + ': ' + @ErrorMsg + ' (Source: ' + @Source + ')'

SET @pDonusDegeri = @Error
SET @pDonusAciklama = @ErrorMsg

-- Write the error to the log
SET @Status = 'HATALI_BITTI'
EXEC spi_BatchLog @JobID, @ErrorMsg, @pComment, @Status

EXEC @Error = sp_OADestroy @oSQLServer
EXEC @Error = sp_OADestroy @oDatabase
EXEC @Error = sp_OADestroy @oQueryResults

return @pDonusDegeri

DONE:
SET @Status = 'BASARILI_BITTI'
SET @pComment = @pComment + replace(@ErrorMsg, '[Microsoft][ODBC SQL Server Driver][SQL Server]', '')
SET @pComment = substring(@pComment, 1, charindex('[IKS]',@pComment) - 1)
-- SET @pComment = @pComment + @ErrorMsg
EXEC spi_BatchLog @JobID, NULL, @pComment, @Status
COMMIT
SET @pDonusAciklama = @pComment
return @pDonusDegeri

GO


Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2002-09-12 : 09:50:45
quote:
I used queryresults, but it seems returning only recordsets if any and corresponding rowcount. For example, an insert statement does not return any thing.
Well, that's because an INSERT operation isn't a query. You must grab the @@ROWCOUNT value immediately after the INSERT and put it into a variable, or SELECT @@ROWCOUNT immediately after. Then you can enumerate the QueryResults and get the row count for any operation. I'm pretty sure that's the only way you're going to get that kind of data.
quote:
For example, I suffer from 01-01-1753 minimum date restriction on MSSQL while transfers.
What data are you storing that actually uses dates earlier than that? If you don't have real data with those values, then this isn't a problem.

One other thing:
quote:
First of all, I don't want to modify original code that will be executed.
That's a very unreasonable approach to take when porting an app from one system to another. There is little chance that you can pick something up line-for-line and bring it over and even get close to having it work correctly. If you slice up a loaf of bread, you will never get back the exact same loaf no matter how cleanly you do it. Trying to write an app that works everywhere without modification only compromises its performance on all platforms.

Additionally, different products have different capabilities; if they didn't there would only be one database product in the world. You will do better to learn what SQL Server can do and use its strengths in your app. I'm not sure exactly what your app requires, but I do know that you can get row counts very easily without using SQL-DMO.

Go to Top of Page

oktayhg
Starting Member

2 Posts

Posted - 2002-09-12 : 11:01:24
Hi Volk,
In general I aggree with you. As in my code, I reached a sol'n anyway. My considerations are below:

1. As I indicated in the title, I wanted to be able to grab rowcounts affected by each statement in any script or procedure. This script or procedure can be dynamically changed or provided by any body. As far as I know from some help search, it is indicated that Microsoft Utilities like Enterprise Manager are/can be developed using SQL-DMO. I think Ouery Analyzer also can be developed using SQL-DMO. So if I had developed my Query Analyzer, how could I get and those "1 rows deleted..." messages? Should I first modify original code then process it? This is my main consideration. Of course, some modifications are required and natural while portings, this is a general issue we encounter during everyday administration of multiplatform environments.

2. Excuse me, but I saw this kind of restriction only on MSSQL platform. I think its root is Sybase. Progress, Teradata, Oracle all support this range of dates.

How can't you save a historical date in your enterprise server? Should you use an sql server just for bank transactions? I don't find this as an acceptable reason?

So I hope a way of my coding my query analyzer, whether using SQL-DMO or another way.

Thank you for your comments, directions.

regards,
Oki

Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2002-09-12 : 11:35:48
quote:
I think Ouery Analyzer also can be developed using SQL-DMO.
As far as I know you can't modify Query Analyzer itself, you'd develop your own application. QA does not use SQL-DMO either, only Enterprise Manager does. Additionally, you can use ADO to work with SQL Server for pretty much any SQL command, if you are creating your own user interface.
quote:
2. Excuse me, but I saw this kind of restriction only on MSSQL platform. I think its root is Sybase. Progress, Teradata, Oracle all support this range of dates.

How can't you save a historical date in your enterprise server? Should you use an sql server just for bank transactions? I don't find this as an acceptable reason?
That was the point of my question: ARE YOU storing data that fits that date range or not? If you're not, and you don't anticipate the need, then it is NOT a restriction. That's like complaining about a restaurant that doesn't serve a type of food that you don't eat anyway.

It does not help to complain about the restrictions of a database product that you will never encounter; and in any case, if that product doesn't do what you need, then don't use it. Oracle has plenty of restrictions too, if I have to use Oracle I work around them.

As far as getting the row counts for all commands submitted to the server, why do you want to do this? Is it for logging purposes? I'm rather confident that using SELECT @@ROWCOUNT (NOT PRINT @@ROWCOUNT, do not use PRINT) will suffice. It might require pre-parsing the SQL statements that are passed to your application. You might also want to look at SQL Profiler, it can be configured to trace SQL commands and provide information on them.

Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-09-13 : 03:27:29
The date range restriction is only a restriction of the datetime datatype. If you want to use value that won't fit in the field then use a different datatype which may take up more space depending on the accuracy you want.
Note that historic dates are country dependent and tend to jump around a lot as calendars were corrected.
For UK (and USA) ten or so days were dropped in 1752 which is why 1753 is the min date otherwise it would make date calculations and validation a bit odd - wonder what those other databases do about that.

==========================================
Cursors are useful if you don't know sql.
DTS can be used in a similar way.
Beer is not cold and it isn't fizzy.
Go to Top of Page
   

- Advertisement -