How to limit results of Stored procedure for MS-SQl - sql

Problem is...I will be provided with a command to execute a procedure...like EXEC SAMPLE_PROCEDURE_NAME, I cannot modify or pass count/number to that procedure
Right now, on execution, the procedure is returning all the rows. I want to limit the number of rows that I receive back
Below are a few things I have tried (Procedure name = Demo4)
This one failed
select top 10 * FROM (EXEC Demo4)
This one failed too
;WITH Results_CTE AS
(
EXEC Demo4
)
select top 10 *
FROM Results_CTE
This one failed too
DECLARE #tmpNewValue TABLE (*)
INSERT INTO #tmpNewValue
EXEC Demo4
select top 10 * FROM #tmpNewValue
I would really appreciate if someone can help on this.

You need to specify the columns in the result set to put them in a table. So:
declare #tmpNewValue table (
col1 type1,
col2 type2,
. . .
);
Then you can insert the rows:
INSERT INTO #tmpNewValue
EXEC Demo4;
And return 10 arbitrary rows:
select top 10 *
from #tmpNewValue;
You need an ORDER BY to get ten specific rows (like "first" whatever that means).
If you want them in insertion order and have no other method, then you can use an identity column in your table:
declare #tmpNewValue table (
id int identity(1, 1),
col1 type1,
col2 type2,
. . .
);
insert into #tmpNewValue (col1, col2, . . . ) -- no `id` column here
exec Demo4;
Then:
select top (10) *
from #tmpNewValue
order by id;
I should add that I strongly discourage returning result sets like this. Stored procedures should not be viewed as queryable objects. Code can break just because someone makes a small modification to the stored procedure -- like adding debugging or auditing code.
There are other ways to handle these situations:
If multiple rows are not needed, then OUTPUT parameters can be used.
In many cases, the stored procedure can be written as a user-defined function.
You can pass in a table variable to return a table (although that requires a user-defined type).

You can limit the rows from the stored procedures just by setting the row count before running the the stored procedure and releasing it later as below
Solution: SET ROWCOUNT 50; EXEC Demo4; SET ROWCOUNT 0;
Description: Running SET ROWCOUNT 50; would limit the result of any query including stored procedures. then you execute the stored procedure as EXEC Demo4; to release the connection from limiting the rows to 50 you have to set it to Zero as SET ROWCOUNT 0;

Related

How to combine 2 results from SQL procedure

I wrote a SQL query, it is 300+ line and I made this as a procedure.
I want to run two times this procedure with different parameters and then want to see all result in one table.
For example:
exec sp_xxxxx 4652,'2022-02-07 00:00:00.000',1
// Returns 2 columns, number of rows can vary
exec sp_xxxxx 4652,'2022-02-14 00:00:00.000',1
// Returns 2 columns, number of rows can vary
I run these together, then I hope to get a result of 4 columns
// 4 column,number of rows can vary
I tried openrowset but SQL blocked.
How can I do this, I would be very happy if you can help.
There's not enough information to provide a demonstrable solution, but the approach should be:
Create temp table #T1(col1, col2)
Create temp table #T2(col1, col2)
Insert into #T1(col1, col2) exec proc
Insert into #T2(col1, col2) exec proc
select t1.col1, t1.col2, t2.col1, t2.col2
from #T1 inner/left/full join #T2 on<criteria>
Also note that prefixing procedures with "sp" is not recommended, this is reserved by MS and indicates a Special Procedure. Choose a different prefix - or no prefix.
Start with creating a table type than matches the output of your procedure.
For example:
CREATE TYPE XxxxxTblType AS TABLE(
Col1 varchar(10) not null,
Col2 decimal(8,2) not null
);
This table type could also be used by your procedure.
Then use a variable with that table type to collect the results from the procedures. Then create a temporary table from that table variable.
declare #Xxxxx XxxxxTblType;
insert into #Xxxxx exec sp_xxxxx 4652,'2022-02-07 00:00:00.000',1;
insert into #Xxxxx exec sp_xxxxx 4652,'2022-02-14 00:00:00.000',1;
select * into #tmpXxxxx from #Xxxxx;
Now you can query the temporary table.
select * from #tmpXxxxx;

Reuse results of SELECT query inside a stored procedure

This is probably a very simple question, but my attempts to search for an answer are thwarted by Google finding answers showing how to reuse a query by making a stored procedure instead. I want to reuse the results of a query inside a stored procedure.
Here's a cut-down example where I've chopped out NOCOUNT, XACT_ABORT, TRANSACTION, TRY, and much of the logic.
CREATE PROCEDURE Do_Something
#userId UNIQUEIDENTIFIER
AS
BEGIN
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT Items.id FROM Items
WHERE Items.userId = #userId
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT Items.id FROM Items
WHERE Items.userId = #userId
)
END
What is the syntax to reuse the results of the duplicated nested SELECT rather than doing it twice?
You can INSERT result of the SELECT into a temporary table or table variable, but it doesn't automatically mean that the overall performance would be better. You need to measure it.
Temp Table
CREATE PROCEDURE Do_Something
#userId UNIQUEIDENTIFIER
AS
BEGIN
CREATE TABLE #Temp(id int);
INSERT INTO #Temp(id)
SELECT Items.id
FROM Items
WHERE Items.userId = #userId;
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM #Temp
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM #Temp
)
DROP TABLE #Temp;
END
Table variable
CREATE PROCEDURE Do_Something
#userId UNIQUEIDENTIFIER
AS
BEGIN
DECLARE #Temp TABLE(id int);
INSERT INTO #Temp(id)
SELECT Items.id
FROM Items
WHERE Items.userId = #userId;
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM #Temp
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM #Temp
)
END
You can declare a table variable to store the results of the select and then simply query that.
CREATE PROCEDURE Do_Something
#userId UNIQUEIDENTIFIER
AS
BEGIN
DECLARE #TempItems TABLE (id int)
INSERT INTO #TempItems
SELECT Items.id FROM Items
WHERE Items.userId = #userId
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM #TempItems
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM #TempItems
)
END
If the subquery is fast and simple - no need to change anything. Item's data is in the cache (if it was not) after the first query, locks are obtained. If the subquery is slow and complicated - store it into a table variable and reuse by the same subquery as listed in the question.
If your question is not related to performance and you are beware of copy-paste: there is no copy-paste. There is the same logic, similar structure and references - yes, you will have almost the same query source code.
In general, it is not the same. Some rows could be deleted from or inserted into Items table after the first query unless your are running under SERIALIZABLE isolation level. Many different things could happen during first delete, between first and second delete statements. Each delete statement also requires it's own execution plan - thus all the information about tables affected and joins must be provided to SERVER anyway. You need to filter by the same source again - yes, you provide subquery with the same source again. There is no "twice" or "reuse" of a partial code. Data collected by a complicated query - yes, it can be reused (without running the same complicated query - by simple querying from prepared source) via temp tables/table variables as mentioned before.

Selecting Data based on a specific condition ,which is the optimal solution using sql statement or stored procedure using cursor in sybase

SELECT distinct(a.acct_num)
FROM customer_acct a,
customer_acct_history b LIKE "%000%"
WHERE a.acct_num *= b.acct_num
AND acct_type='C'
This Query would return a list of acct numbers from the tables. Based on this output . I am planning to run another Query and select various data from other tables . The second query consists of various joins and also a Group by and Order by .I would like to select only the top 1 data from this Query for every account number from the first query I didnt paste that here since it is a Big query .
I am planning to use a Cursor with a For Loop to do the Process. Is it an Efficient one or can it be done just using Sql statements aand Loops . Any Synatx would be helpful to complete the process with an optimized and time saving way .
You can create a temp table and assign all the account numbers from the first query.Put an identity column to your temp table so that its easy to loop through the table.
create table #tmp_account(ID int identity not null,acct_num varchar(100)not null)
Now loop through the table using ID as the counter.
Declare #vc_id int
SELECT #vc_id=1
set rowcount 1
WHILE EXISTS (SELECT 1 FROM #tmp_account )
begin
select #ac_nm=acct_num from #tmp_account where ID=#vc_id
-- put your 2nd query here..you can insert resultset into another temp table.
delete from #tmp_account where ID=#vc_id
select #vc_id=#vc_id+1
end
set rowcount 0
Consider the use of a cursor.
An example can be found here.
http://infocenter.sybase.com/help/in...ses/X61512.htm
declare c_account cursor for
SELECT distinct(a.acct_num)
FROM customer_acct a,
customer_acct_history b LIKE "%000%"
WHERE a.acct_num *= b.acct_num AND acct_type='C'
#acc_num integer -- or whatever the column type is
begin
create table #foo ( col1 int, col2 varchar(255), col3 datetime)
open c_account
fetch c_account into #acc_num
while ##sqlstatus = 0
begin
insert into #foo (col1, col2, col3)
select top 1
col1, col2, col3
from
other_table ot
where
ot.col = #acc_num
fetch c_account into #acc_num
end
close c_account
deallocate c_account
end
go
Hope that helps, but I suspect this could be faster if you do this as a series of joins.

How to selectively return rows inside a stored procedure on SQL Server?

I have a base stored procedure simply returning a select from the database, like this:
CREATE PROCEDURE MyProcedure
AS
BEGIN
SELECT * FROM MyTable
END
GO
But now I need to execute some logic for every row of my select. According to the result I need to return or not this row. I would have my select statement running with a cursor, checking the rule and return or not the row. Something like this:
CREATE PROCEDURE MyProcedure
AS
BEGIN
DECLARE CURSOR_MYCURSOR FOR SELECT Id, Name FROM MyTable
OPEN CURSOR_MYCURSOR
FETCH NEXT FROM CURSOR_MYCURSOR INTO #OUTPUT1, #OUTPUT2
WHILE (##FETCH_STATUS=0)
BEGIN
IF (SOME_CHECK)
SELECT #OUTPUT1, #OUTPUT2
ELSE
--WILL RETURN SOMETHING ELSE
END
END
GO
The first problem is that everytime I do SELECT #OUTPUT1, #OUTPUT2 the rows are sent back as different result sets and not in a single table as I would need.
Sure, applying some logic to a row sounds like a "FUNCTION" job. But I can't use the result of the function to filter the results being selected. That is because when my check returns false I need to select something else to replace the faulty row. So, I need to return the faulty rows so I can be aware of them and replace by some other row.
The other problem with this method is that I would need to declare quite a few variables so that I can output them through the cursor iteration. And those variables would need to follow the data types for the original table attributes and somehow not getting out of sync if something changes on the original tables.
So, what is the best approach to return a single result set based on a criteria?
Thanks in advance.
I recommend use of cursors but easy solution to your question would be to use table variable or temp table
DECLARE #MyTable TABLE
(
ColumnOne VARCHAR(20)
,ColumnTwo VARCHAR(20)
)
CREATE TABLE #MyTable
(
ColumnOne VARCHAR(20)
,ColumnTwo VARCHAR(20)
)
than inside your cursors you can insert records that match your logic
INSERT INTO #MyTable VALUES (#Output1, #Output2)
INSERT INTO #MyTable VALUES (#Output1, #Output2)
after you done with cursor just select everything from table
SELECT * FROM #MyTable
SELECT * FROM #MyTable

SELECT against stored procedure SQL Server

SELECT Val from storedp_Value within the query editor of SQL Server Management Studio, is this possible?
UPDATE
I tried to create a temp table but it didn't seem to work hence why I asked here.
CREATE TABLE #Result
(
batchno_seq_no int
)
INSERT #Result EXEC storedp_UPDATEBATCH
SELECT * from #Result
DROP TABLE #Result
RETURN
Stored Procedure UpdateBatch
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
What am I doing wrong and how do I call it from the query window?
UPDATE #2
Ok, I'd appreciate help on this one, direction or anything - this is what I'm trying to achieve.
select batchno_seq from (delete from batchno_seq;insert into batchno_seq default values;
select * from batchno_seq) BATCHNO
INTO TEMP_DW_EKSTICKER_CLASSIC
This is part of a larger select statement. Any help would be much appreciated. Essentially this SQL is broken as we've migrated for Oracle.
Well, no. To select from a stored procedure you can do the following:
declare #t table (
-- columns that are returned here
);
insert into #t(<column list here>)
exec('storedp_Value');
If you are using the results from a stored procedure in this way and you wrote the stored procedure, seriously consider changing the code to be a view or user defined function. In many cases, you can replace such code with a simpler, better suited construct.
This is not possible in sql server, you can insert the results into a temp table and then further query that
CREATE TABLE #temp ( /* columns */ )
INSERT INTO #temp ( /* columns */ )
EXEC sp_MyStoredProc
SELECT * FROM #temp
WHERE 1=1
DROP TABLE #temp
Or you can use OPENQUERY but this requires setting up a linked server, the SQL is
SELECT * FROM (ThisServer, 'Database.Schema.ProcedureName <params>')
The best article (in my opinion) about all possible methods for sharing data between stored procedures in SQL Server you can find here: http://www.sommarskog.se/share_data.html
Try this
Change 'Return'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
to 'Select'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
SELECT #batchno_seq
My approach
select * into new_table from (select t1.col1,t1.col2,..
from table1 t1
union
select t2.cola,t2.colb,..
from table2 t2) as union_table
I MUST be missing something.
Since your stored procedure does not return a result set, and instead returns an integer, using the RETURN functionality of stored procs, you simply CANNOT INSERT into ANY table (since there isn't any result set coming back, at all).
BUT, you can (assuming that this is done iteratively, and not over a set) simply store the return value into a local variable, and insert that variable's value into whatever table is necessary.
However, if you simply want to return the value in the results of a Query Window in SSMS, doing the INSERT and SELECTING is overkill.
It seems to me like THIS would suffice (in a query window):
DECLARE #RetVal INT = 0;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
EXEC #RetVal = storedp_UPDATEBATCH;
COMMIT TRANSACTION;
SELECT #RetVal;
--OR
--PRINT #RetVal;
If this is way far off base, please provide the DDL for "batchno_seq", maybe I can be of better assistance that way.
Cheers!