How can I count the rows returned from a stored-procedure that returns a table? - sql

Is it possible to count how many rows returned by a stored-procedure which returns a simple table?

Return ##ROWCOUNT as either an output parameter or second result set.
Or add another column to the one resultset using a COUNT..OVER construct
...
COUNT(*) OVER () AS RowCount
...
Or read it in the client code eg DataTable.Rows.Count

Related

SQL Server variables and direct values not returning same results

I'm working on building a sql query to fetch some details from a table. And I am using a variable that is assigned with a value in where condition. However, when the value assigned to the variable is directly given to the where condition it returns a different result set. I cannot disclose the entire query here due to the nature of work but I hope someone could help me.
declare #filterParam varchar(255) = 'Y'
Select .......
from Table A
where
...
A.column!= #filterParam
This returns some number of rows but if i replace the variable with its actual value then 0 rows are returned
Select .......
from Table A
where
...
A.column!= 'Y'
0 rows is what the expected result is. But why is the SQL Server returning result when the value is assigned to a variable and used it against the where condition.
Thanks in advance.

Fetch multiple rows into a variable

I am attempting to fetch multiple unique account ID's (transactions.ID) and store in Variable v_Trxn. The problem is that the query count returns incorrect. Expected result is 300485 rows.
DECLARE
l_Partition transactions.Partitionkey%TYPE;
v_Trxn transactions.ID%TYPE;
l_Count number;
CURSOR v_Trxn_cur IS
SELECT ID
FROM transactions
WHERE Partitionkey > l_Partition;
BEGIN
SELECT dl_common.Get_Partitionkey(aInstitutionId => DL_COMMON.Get_InstitutionId , aDate => add_months(sysdate,-4)) INTO l_Partition FROM Dual;
OPEN v_Trxn_Cur;
LOOP
FETCH v_Trxn_Cur INTO v_Trxn;
EXIT WHEN v_Trxn_Cur%NOTFOUND;
END LOOP;
SELECT COUNT(UNIQUE(ID)) INTO l_Count FROM transactions WHERE ID In v_Trxn;
DBMS_OUTPUT.PUT_LINE(l_Count || ' Number of Unique Sernos');
CLOSE v_Trxn_Cur;
End;
Output: 1 Number of Unique Sernos
If I put the partitionkey directly into the WHERE clause I get the expected number of rows.
SELECT
dl_common.Get_Partitionkey(aInstitutionId => DL_COMMON.Get_InstitutionId,
aDate => add_months(sysdate, -4)) PARTITION
FROM Dual;
Returns: PARTITION 2914365
SELECT
COUNT(UNIQUE(ID)) C_COUNT
FROM transactions C
WHERE C.Partitionkey > 2914365
Returns: C_COUNT 300485
The expected number of rows is fetched.
Please explain what I am doing wrong.
You're repeatedly selecting a single ID into your scalar variable. It can never hold more than a single value at a time. After the first iteration of your loop your variable holds the first ID returned by your cursor query (which is indeterminate because you don't have an order-by clause). After the second iteration your variable holds the second ID returned by the cursor query. It does not, and cannot, hold both values simultaneously.
To hold multiple values you would need to bulk select into a collection type, which needs to be declared at schema level (i.e. an SQL type, not a PL/SQL type) if you really want to use it as part of a later SQL query.
But storing hundreds of thousands of values in a collection is going to consume a significant amount of memory. Without knowing what you're really going to do with the values once you have them it isn't clear if that is just a price you'll have to pay; if you can do your work in batches (of, say, 1000 IDs at a time; if row-by-row processing is appropriate; or if you really want a join as part of a larger query, without holding them as a PL/SQL variable at all.
You need to use VARRAY OR NESTED TABLES FOR THIS PURPOSE.
You can hold multiple values like this-
Type var_dnames IS VARRAY(1000) transactions.ID%TYPE;
v_Trxn var_dnames;
Now "v_Trxn" can hold multiple values from fetch statement.

SQL Server Stored Procedure - Use Row Count in Select query

My stored procedure (SQL Server 2005) returns a dataset where one field depends, among other things, on the number of rows returned by the query. I can make a simplified first query that allows me to get ##ROWCOUNT but, in that case, the procedure returns the two sets, which is not what I want.
I tried putting the first query in a WITH statement but haven't found the syntax to extract the row count and put it in a variable that I could use in the second query. An alternative would be to get ##ROWCOUNT from the first query and tell the procedure to return only the result of the second query.
There are probably better ways to do that but my expertise in SQL is quite limited...
Thanks for any help!
Is this what you're looking for? If not, could you please describe your problem in more details (perhaps, with code snippets)
alter procedure ComplicatedStoredProcedure as
begin
declare #lastQueryRowCount int
-- Storing the number of rows returned by the first query into a variable.
select #lastQueryRowCount =
-- First resultset (not seen by caller).
(select count(*) from A where ID > 100)
-- Second resultset. This will be the actual result returned from the SP.
select * from B where SomeDependentField > #lastQueryRowCount
end

using scalar function output in an update

Suppose I have a 2 column table with columns (arg, value) and a user-defined function foo.
Is there a way to have an update query that goes through the table and calls foo with argument arg and sticks the results in column value for every row in the table?
Assuming SQL Server the syntax is
Update YourTable
SET value = dbo.foo(arg)
It is often more efficient to not use scalar UDFs for Row by Row processing however. What is the scalar UDF doing?

Complex Cursors for returning multiple rows

Each row in a cursor should be joined with another table and the whole result should be returned a one cursor
Say cursor1 return 5 rows.
Each of these 5 rows should be joined with table1.
and the final result for all the 5 rows should be returned a 1 row.
Plz help
It is rather tricky to combine the fetched records from a ref cursor with the result set of another query. A much better idea would be to open just the one ref cursor with a SELECT which joins all the relevant tables.
The question isn't clear, but it sounds like what you need is something like this
a) Define an object type with the shape of your result row
b) Define a collection of that object type
c) Create a function with a return type of the collection type - this could take in cursor A as a parameter (SYS_REFCURSOR), join each row in cursor A to table B, and then use PIPE ROW for each result row.
d) If the final result is needed as a cursor, then another function along the lines of
FUNCTION complex_query(in_cursor SYS_REFCURSOR)
RETURN SYS_REFCURSOR
IS
lreturn SYS_REFCURSOR;
BEGIN
OPEN lreturn FOR
(SELECT * FROM TABLE(convert_to_collection(in_cursor)));
RETURN lreturn;
END;
Alternatively, you could just do the SELECT * FROM TABLE(convert_to_collection(in_cursor)) directly.
What I don't understand is the requirement that everything is returned as 1 row.