Checking whether value exists in results of a stored procedure - sql-server

I have a stored procedure which returns a list of IDs for a particular set of generators I want to be able to then use the results of this stored procedure as part of another query.
Can I write a query like:
select * from table where id in (exec dbo.storedprocedurename)

Using table variable and JOIN you can achieve this. Store the procedure result into the table.
DECLARE #ProcOutput TABLE (Id INT);
INSERT INTO #ProcOutput (Id)
EXEC [dbo].[storedprocedurename]
SELECT T.*
FROM Table T
JOIN #ProcOutput O ON O.Id = T.Id
If the procedure returns multiple entries, according to the output you can re-design the table's schema.

If your output of procedure is 2 columns then you may try this:
INSERT INTO MyTable
(
Col1,
Col2
)
EXEC [dbo].[storedprocedurename]
GO
SELECT * FROM TABLE WHERE ID IN (SELECT Col1 from Mytable)

Related

Multiple values in one parameter in a stored procedure

My stored procedure needs to insert multiple products in the [Order Details] table.
One OrderID = Many products.
I saw a code where you will create a temporary table like a list to store multiple values. But I don't know how to use it when the values is not pre-defined or is a user input.
--I want to input multiple ProductID in this temporary table
DECLARE #myOrders table (ID int)
INSERT INTO #myOrders ("")
--Then get data from the Products table and input the data in Order Details
INSERT INTO [Order Details] (ProductID)
SELECT ProductID From Products
WHERE ProductID IN (SELECT ID FROM #myOrders)
Sample pic of Order details
First you need to define type like following
CREATE TYPE ProductList AS TABLE
(
ProductId INT
)
GO
Then create your procedure like following
ALTER PROCEDURE USP_TEST_PROC (#OrderId INT,#Produt_Id_List ProductList READONLY)
AS
BEGIN
DECLARE #OrderDetails TABLE(OrderId INT, ProductID INT,UnitPrice DECIMAL(18,2),Quantity INT, Discount DECIMAL(18,2))
DECLARE #Products TABLE(ProductID INT,UnitPrice DECIMAL(18,2),Quantity INT, Discount DECIMAL(18,2))
INSERT INTO #OrderDetails (OrderId, ProductID,UnitPrice,Quantity, Discount)
SELECT #OrderId, ProductID,UnitPrice,Quantity,Discount FROM #Products WHERE ProductID IN (SELECT ProductId FROM #Produt_Id_List)
SELECT * FROM #OrderDetails
END
Then prepare table variable to put values like following
DECLARE #PList ProductList;
INSERT #PList VALUES (1),(2),(3)
Finally call procedure
EXEC USP_TEST_PROC 100,#PList
Thanks
Stored procedures accept table inputs in the form of table values parameters. Look at the documentation here
https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine
This includes an example also on how to invoke such a stored procedure.
You can directly use the TVP similar to a table variable (#myOrders in you sample) in the stored procedure body.
If you are looking to also call that stored procedure from ADO.NET, below article has a good description.
https://www.codeproject.com/Articles/39161/C-and-Table-Value-Parameters

Can you cache the results of a subquery that's used repeatedly in a stored procedure?

I have a series of queries being UNION'd together. Each query has a WHERE... IN clause that compares against the same list of IDs.
In a simplified form for example purposes it looks like this:
SELECT * FROM MyTable
WHERE AuthorUserId IN (SELECT UserId FROM Users WHERE TeamId = #teamId)
UNION
SELECT * FROM MyTable
WHERE PublisherUserId IN (SELECT UserId FROM USERS WHERE TeamId = #teamId)
UNION...
and so on. #teamId is an int stored procedure parameter.
Is there a way to tell SQL Server to hold on to the result set of
SELECT UserId FROM USERS WHERE TeamId = #teamId
so it doesn't fetch it for each SELECT?
One way you could do this is by capturing the results of that query and storing it in a temp table, and JOINing to those results in your query:
Declare #UserIds Table (UserId Int)
Insert #UserIds (UserId)
SELECT UserId
FROM Users
WHERE TeamId = #teamId
SELECT M.*
FROM MyTable M
JOIN #UserIds U ON M.AuthorUserId = U.UserId
UNION
SELECT M.*
FROM MyTable M
JOIN #UserIds U ON M.PublisherUserId = U.UserId
UNION...
SQL server is smart enough to store results of same query if the parameters are same. If your subquery is not using session variables, you will be fine. You can also put index on TeamId which will make this query faster.
If you are still worried about it and using any programming language to get data from SP, then you should store it in a variable in code and then pass that result set into SP.
Second option would be to store it in temp table and then query it from temp table

How to write two queries in a stored procedure when second query depend on first query output in SQL Server

I want to write a stored procedure in which I have two select queries and second queries has where clause that depends on first query output, as
create procedure getRecord
As
Begin
select *
from tblUser
where userName = 'Johan'
select *
from tblDistrict
where id between #id1 and #id2
end
Here #id1 and #id2 are the first and last id of resultant table of first query
Try this
create procedure getRecord
As
Begin
select * from tblDistrict where id IN (select Id from tblUser Where userName = 'Johan')
End
There are a variety of ways to achieve this.
If you only need the results from the second query, and the first is merely to filter results for the second, then you can nest the first query within a join e.g.
select *
from tblDistrict
inner join (select
MAX(id) as maxId,
MIN(id) as minId
from tblUser
where userName = 'Johan') as tbl1 ON
tblDistrict.id between tbl1.minId and tbl1.minId
If you need outputs from both queries, you can make use of table variables or temp tables. e.g.
select *
into #tmpTbl1
from tblUser
where userName = 'Johan'
declare #minId INT,#maxId INT
select #minId=min(id),#maxId=max(id) from #tmpTbl1
select * from #tmpTbl1
select * from tblDistrict where id between #minId and #maxId
drop table #tmpTbl1
I'm assuming you are using between minId and maxId for a reason and therefore didn't change logic to find an exact id matches for for 'Johan' between tblUser and tblDistrict
The second example can easily be modified to use Table variables instead of temp tables. The performance difference is outside the scope for this question though.
Try this
create procedure getRecord As Begin
declare #min_id int,
#max_id int
select #min_id = min(id),
#max_id = max(id)
from tblUser
Where userName = 'Johan';
select * from tblDistrict where id between #min_id and #max_id
End
Use a Subquery.
Subqueries are queries that you can use inside of other queries. They always execute from the innermost query out. From your case, just use the first query as a subquery like this:
create procedure getRecord
AS
BEGIN
SELECT *
FROM tblDistrict
WHERE id IN (SELECT *
FROM tblUser
WHERE userName = 'Johan')
END
Keep in mind subqueries are difficult to read and debug. You might want to limit the number of nested queries and format it so that it is easy to follow as in the case here.

Assign multiple data to a variable in sql server stored procedure

I want to assign multiple values to a variable from a SELECT statement in a stored procedure.
The code goes like this
DECLARE #ProjectExecutionPlanId INT=NULL
SELECT #ProjectExecutionPlanId = (SELECT [ID] FROM [dbo].[ProjectExecutionPlan]
WHERE ProjectDetailID=#PID)
#PID in the input to the stored procedure.
The SELECT statement returns multiple values. So I am getting error.
This answer is based on your comment:
I want to delete multiple rows from the ProjectExecutionPlanExecution
table which is dependent on ProjectExecutionPlan table.There are
multiple plans in ProjectExecutionPlan table. So I will get multiple
IDs
Delete From ProjectExecutionPlanExecution
Where ProjectExecutionPlanId In (SELECT [ID]
FROM [dbo].[ProjectExecutionPlan]
WHERE ProjectDetailID=#PID)
Or
Delete pe From ProjectExecutionPlanExecution pe
Join ProjectExecutionPlan p On pe.ProjectExecutionPlanID = p.ID
WHERE p.ProjectDetailID=#PID

SQL Server, Insert into table from select query?

I would fill a table from a query in a stored procedure,
This works:
SELECT *
INTO #tmpTable
FROM MyTable
This works:
SELECT TOP (1) *
FROM MyTable
WHERE Land = #Land
but how do I fill #tmpTable with
SELECT TOP (1) *
FROM MyTable
WHERE Land = #Land
Because the #temp Table's scope is limited to its session (SPID), i.e. the Stored Procedure itself. After the SP execution completes the #temp table is Dropped.
Also while the SP is being executed you cannot see the #temp Table from other sessions (SPID)
USE Global temp table like ##temp even it can be accessible after execution of sp also

Resources