I have a query and just want the rowcount to show up, not the results from the proc I'm calling.
For example this:
exec GetSomething
#UserID = 112233,
#MaxAge = 50,
... etc.
SET #Count = ##rowcount
SELECT #Count
returns not only the count but also the first recordset's list of resulting records before the count is selected.
How can I still do this count but not show the recordset results?
DECLARE #Something TABLE (
...
)
INSERT INTO #Something
EXECUTE GetSomething
#UserID = 112233,
#MaxAge = 50,
... etc.;
SET #Count = ##rowcount
SELECT #Count
You might try using OPENROWSET but you have to make sure it's enabled:
SELECT count(*) FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC GetSomething')
To enabled OPENROWSET:
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
See MSDN on OPENROWSET: http://msdn.microsoft.com/en-us/library/ms190312.aspx
Related
This seems like it should be pretty simple, but I cannot find a way to do it.
set nocount on;
Update MyTable
set MyField = 'value'
--where 1 = 1/0 -- comment in to test getting an error.
print convert(varchar, ##error)
print "blah blah" + convert(nvarchar, ##rowcount) -- this is always zero because of the previous statement
I tried storing them in a variable, but setting the variable generates a new ##rowcount and new ##error value.
I also tried using an if condition, because i don't care about the row count. But evaluating the if seems to also reset ##rowcount.
You can do it in a single statement, like this:
DECLARE #err INT, #cnt INT
SELECT #err=##ERROR, #cnt=##ROWCOUNT
I have a stored procedure that cannot be modified, I'm going to stress this before anyone suggests I re-write the stored procedure or add the query from inside the stored procedure into a function.
The procedure lives on another database that we have very limited access to; so what I want to do is somehow wrap the stored procedure in a query, function or stored procedure that will allow me to select the top N rows from the returned data.
Ideally I would be able to call something like...
DECLARE #ForeName varchar(50)
DECLARE #Surname varchar(50)
DECLARE #DOB datetime
DECLARE #Sex varchar(1)
SET #Surname = 'Smith'
SELECT TOP 10 (
EXECUTE #RC = [Some_Other_Database].[dbo].[sp_search_demographics]
,#ForeName
,#Surname
,#DOB
,#Sex
)
GO
edit: (I should also note that the stored procedure returns a parameter containing the row count as well as the rows)
edit2: I should also note that I'm using MS SQL Server 2008 R2
I'm aware that this is in no way correct, is there any way to do something like this? at the moment for vague queries we are getting thousands of rows returned; which is slowing the server considerably.
I have done some Googling and stack-overflowing for a solution but unfortunately all the advice I could find involved modifying the stored procedure.
Look up EXEC SP_EXECUTESQL(#SQL)
However the problem will be that the called sp will still return all the rows, so you may not get the improvement in performance you are looking for.
You can also set the number of rows returned by a query - but depends on your access level
http://blog.sqlauthority.com/2007/04/30/sql-server-set-rowcount-retrieving-or-limiting-the-first-n-records-from-a-sql-query/
Hope this helps
Declare #i Numeric(18,2)
Declare #strSQL nvarchar(1000)
select #i = Round(COUNT(1)/10,2) from tb_Item
print(#i)
Declare #j int = 0
Declare #rem numeric(18,2)
select #rem = COUNT(1) - ((COUNT(1)/10) * 10) from tb_Item
while #i > 0
Begin
set #j = (#j + 1);
if #j = 1
Begin
WITH OrderedOrders AS
(
select
ROW_NUMBER() over(order by ItemID) AS RowNumber
,ItemName
from tb_Item
)
SELECT ItemName, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN (#j*10)-10 AND #j*10;
End
Else
Begin
WITH OrderedOrders AS
(
select
ROW_NUMBER() over(order by ItemID) AS RowNumber
,ItemName
from tb_Item
)
SELECT ItemName, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN ((#j*10)-10) + 1 AND #j*10;
End
set #i = #i - 1;
end;
WITH OrderedOrders AS
(
select
ROW_NUMBER() over(order by ItemID) AS RowNumber
,ItemName
from tb_Item
)
SELECT ItemName, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN (#j*10)+1 and (#j*10) + #rem ;
Link
##Rowcount is used to inform the number of rows affected for the last
select,insert,update or delete statements
declare #row int select 100 if ##rowcount>0 set #row=##rowcount ...
The above will return 0 because as soon as if ##rowcount>0 is executed
it is reset to 0 as it doesn't return any rows. So always assign to
variable first
Why does statement if ##rowcount>0 reset ##rowcount to 0? Isn't the value of ##rowcount affected only by select,insert,update and delete statements?
thank you
It is affected by the last statement. Like this SET statement
Declare #row int
select 100 union all select 200 union all select 300
set #row = ##rowcount;
SELECT #row, ##rowcount
If you read the actual Microsoft SQL Server Docs on MSDN, it gives examples of what statements affect ##ROWCOUNT. For example "such as" implies other statements like IF will also set it to zero
Statements such as USE, SET <option>, DEALLOCATE CURSOR, CLOSE CURSOR, BEGIN TRANSACTION or COMMIT TRANSACTION reset the ROWCOUNT value to 0.
Well,
I faced similar issue using sybase, which indicates that something might be wrong with "if".
declare #counter1 int
declare #counter2 int
select #counter1 = ##rowcount
if ##rowcount = 0 return
select #counter2 = ##rowcount
the output is:
counter1 = 3
counter2 = 0
I would expect 3(original one) or 1(because of Select).
This is even more strange because of
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc38151.1540/doc/html/san1278452893271.html
"The ##rowcount is not reset to zero by any statement which does not affect rows, such as an IF statement."
on other hand there is a lot of confusion how it really works(based on discussion in internet)
At the end in my solution in first line I assign ##rowcount to variable and my logic is based on that variable
I have a TSQL sproc that builds a query as and executes it as follows:
EXEC (#sqlTop + #sqlBody + #sqlBottom)
#sqlTop contains something like SELECT TOP(x) col1, col2, col3...
TOP(x) will limit the rows returned, so later I want to know what the actual number of rows in the table is that match the query.
I then replace #sqlTop with something like:
EXEC ('SELECT #ActualNumberOfResults = COUNT(*) ' + #sqlBody)
I can see why this is not working, and why a value not declared error occurs, but I think it adequately describes what I'm trying to accomplish.
Any ideas?
use sp_executesql and an output parameter
example
DECLARE #sqlBody VARCHAR(500),#TableCount INT, #SQL NVARCHAR(1000)
SELECT #sqlBody = 'from sysobjects'
SELECT #SQL = N'SELECT #TableCount = COUNT(*) ' + #sqlBody
EXEC sp_executesql #SQL, N'#TableCount INT OUTPUT', #TableCount OUTPUT
SELECT #TableCount
GO
You could instead have the dynamic query return the result as a row set, which you would then insert into a table variable (could be a temporary or ordinary table as well) using the INSERT ... EXEC syntax. Afterwards you can just read the saved value into a variable using SELECT #var = ...:
DECLARE #rowcount TABLE (Value int);
INSERT INTO #rowcount
EXEC('SELECT COUNT(*) ' + #sqlBody);
SELECT #ActualNumberOfResults = Value FROM #rowcount;
Late in the day, but I found this method much simpler:
-- test setup
DECLARE #sqlBody nvarchar(max) = N'SELECT MyField FROM dbo.MyTable WHERE MyOtherField = ''x''';
DECLARE #ActualNumberOfResults int;
-- the goods
EXEC sp_executesql #sqlBody;
SET #ActualNumberOfResults = ##ROWCOUNT;
SELECT #ActualNumberOfResults;
After executing your actual query store the result of ##ROWCOUNT in any variable which you can use later.
EXEC sp_executesql 'SELECT TOP 10 FROM ABX'
SET #TotRecord = ##ROWCOUNT into your variable for later use.
Keep in mind that dynamic SQL has its own scope. Any variable declared/modified there will go out of scope after your EXEC or your sp_executesql.
Suggest writing to a temp table, which will be in scope to your dynamic SQL statement, and outside.
Perhaps put it in your sqlBottom:
CREATE TABLE ##tempCounter(MyNum int);
EXEC('SELECT #ActualNumberOfResults = COUNT(*) ' + #sqlBody +
'; INSERT INTO ##tempCounter(MyNum) VALUES(#ActualNumberOfResults);');
SELECT MyNum FROM ##tempCounter;
You can use output variable in SP_EXECUTESQL
DECLARE #SQL NVARCHAR(MAX);
DECLARE #ParamDefinition NVARCHAR(100) = '#ROW_SQL INT OUTPUT'
DECLARE #AFFECTED_ROWS INT;
SELECT
#SQL = N'SELECT 1 UNION ALL SELECT 2'
SELECT #SQL += 'SELECT #ROW_SQL = ##ROWCOUNT;';
EXEC SP_EXECUTESQL #SQL, #ParamDefinition, #ROW_SQL=#AFFECTED_ROWS OUTPUT;
PRINT 'Number of affected rows: ' + CAST(#AFFECTED_ROWS AS VARCHAR(20));
Ouput:
SQL2.sql: Number of affected rows: 2
Thanks Jesus Fernandez!
The only problem with the answers that create temporary tables (either using "DECLARE #rowcount TABLE" or "CREATE TABLE ##tempCounter(MyNum int)") is that you're having to read all the affected records off disk into memory. If you're expecting a large number of records this may take some time.
So if the answer is likely to be large the "use sp_executesql and an output parameter" solution is a more efficient answer. And it does appear to work.
In an SQL Server 2005 database, I have a stored procedure. I get some date in put them in a temp table. I'd like loop in this temp table and depending of the value of some fields change the value of others and make some check. I have to do this for each row.
How can I do this ?
thanks,
UPDATE1
BEGIN
SET NOCOUNT ON
--Create temp table
CREATE TABLE #MyTempTable(
id int IDENTITY(1, 1),
PriceMax int,
PriceMin int
)
-- Insert in temp table
INSERT INTO #tmpReconciliation (PriceMax, PriceMin)
SELECT PriceMax = PriceMaxProduct,
PriceMin = PriceMinProduct
FROM Products
DECLARE #RowNum int
SELECT #RowNum = Count(*) From #MyTempTable
WHILE #RowNum > 0
BEGIN
if(....)
PriceMin = 0
....
END
--Drop temp table
DROP TABLE #MyTempTable
END
I read MSDN documentation for WHILE loop and CURSOR.
For example, let's imagine your temp table is named Employee :
DECLARE #Emp_id int
DECLARE Employee_Cursor CURSOR FOR
SELECT EmployeeID
FROM Employee;
OPEN Employee_Cursor;
FETCH NEXT FROM Employee_Cursor INTO #Emp_id;
WHILE ##FETCH_STATUS = 0
BEGIN
-- Here your actions
PRINT #Emp_id
FETCH NEXT FROM Employee_Cursor INTO #Emp_id;
END;
CLOSE Employee_Cursor;
DEALLOCATE Employee_Cursor;
GO
Here I decided to print EmployeeId, but everything is possible.
Tell us what are your checks, and what your temp table looks like if you need more help.
Can't you just use a cursor and inside the cursor run an update statement??
Cursors: http://www.jackdonnell.com/articles/SQL_CURSOR.htm