Assign multiple data to a variable in sql server stored procedure - sql-server

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

Related

Use output of procedure in a new procedure SQL Server [duplicate]

I'm not sure if this is something I should do in T-SQL or not, and I'm pretty sure using the word 'iterate' was wrong in this context, since you should never iterate anything in sql. It should be a set based operation, correct? Anyway, here's the scenario:
I have a stored proc that returns many uniqueidentifiers (single column results). These ids are the primary keys of records in a another table. I need to set a flag on all the corresponding records in that table.
How do I do this without the use of cursors? Should be an easy one for you sql gurus!
This may not be the most efficient, but I would create a temp table to hold the results of the stored proc and then use that in a join against the target table. For example:
CREATE TABLE #t (uniqueid int)
INSERT INTO #t EXEC p_YourStoredProc
UPDATE TargetTable
SET a.FlagColumn = 1
FROM TargetTable a JOIN #t b
ON a.uniqueid = b.uniqueid
DROP TABLE #t
You could also change your stored proc to a user-defined function that returns a table with your uniqueidentifiers. You can joing directly to the UDF and treat it like a table which avoids having to create the extra temp table explicitly. Also, you can pass parameters into the function as you're calling it, making this a very flexible solution.
CREATE FUNCTION dbo.udfGetUniqueIDs
()
RETURNS TABLE
AS
RETURN
(
SELECT uniqueid FROM dbo.SomeWhere
)
GO
UPDATE dbo.TargetTable
SET a.FlagColumn = 1
FROM dbo.TargetTable a INNER JOIN dbo.udfGetUniqueIDs() b
ON a.uniqueid = b.uniqueid
Edit:
This will work on SQL Server 2000 and up...
Insert the results of the stored proc into a temporary table and join this to the table you want to update:
INSERT INTO #WorkTable
EXEC usp_WorkResults
UPDATE DataTable
SET Flag = Whatever
FROM DataTable
INNER JOIN #WorkTable
ON DataTable.Ket = #WorkTable.Key
If you upgrade to SQL 2008 then you can pass table parameters I believe. Otherwise, you're stuck with a global temporary table or creating a permanent table that includes a column for some sort of process ID to identify which call to the stored procedure is relevant.
How much room do you have in changing the stored procedure that generates the IDs? You could add code in there to handle it or have a parameter that lets you optionally flag the rows when it is called.
Use temporary tables or a table variable (you are using SS2005).
Although, that's not nest-able - if a stored proc uses that method then you can't dumpt that output into a temp table.
An ugly solution would be to have your procedure return the "next" id each time it is called by using the other table (or some flag on the existing table) to filter out the rows that it has already returned
You can use a temp table or table variable with an additional column:
DECLARE #MyTable TABLE (
Column1 uniqueidentifer,
...,
Checked bit
)
INSERT INTO #MyTable
SELECT [...], 0 FROM MyTable WHERE [...]
DECLARE #Continue bit
SET #Continue = 1
WHILE (#Continue)
BEGIN
SELECT #var1 = Column1,
#var2 = Column2,
...
FROM #MyTable
WHERE Checked = 1
IF #var1 IS NULL
SET #Continue = 0
ELSE
BEGIN
...
UPDATE #MyTable SET Checked = 1 WHERE Column1 = #var1
END
END
Edit: Actually, in your situation a join will be better; the code above is a cursorless iteration, which is overkill for your situation.

Checking whether value exists in results of a stored procedure

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)

Table Design for storing dynamic SQL and Stored procedure

I want to store few compiled stored procedure in a table and want to fire them dynamically. The procedures will be fired in an another procedure name GetDetails. I have designed the table as following:
Table: SQLtab
Id SQLText ParamId
1 GetProdDetails 1
2 GetSuppDetails 2
Table: SQLParams
ParamId SQLParam
1 prodId
2 suppId
The parameters of the compiled procedure will be determined by the outer procedure (GetDetails) which will read the procedure names from the SQLtab table and fire them. So, I cannot store the procedure parameter values in the table. The procedure GetDetails runs a query and determines the parameter values for prodId, suppId. I am planning to create a temporary table to store parameter values as following:
Id SQLText ParamVal
1 GetProdDetails 10
2 GetSuppDetails 12
Once the temporary table is created in the outer procedure, I can fire the procedures dynamically using parameter values. Somehow, I feel this is not the best table/procedure design. Could anybody suggest a better design?
Why bother creating these tables and maintaining them when SQL Server cataloge views does it for you.
I would simply use the following query to get the procedure name and its parameters
SELECT po.name AS [Proc Name]
,pa.name AS [Param Name]
FROM sys.procedures po
INNER JOIN sys.parameters pa ON po.object_id = pa.object_id
WHERE po.name LIKE '%ProcName%'
-- AND po.is_ms_shipped = 0 --<-- add more filters as required

Unable to drop a temporary table

I have a stored procedure which uses a temporary table. The thing is that I've tried to use the temporary table more than one time in different SELECT INTO statements. Of course, before issuing the next statement I have issued a DROP #TempTableName and then issue the SELECT INTO statement. Apparently this DROP statement isn't enough since the next SELECT INTO statement complains that the object #TempTableName already exist - SSMS output is:
Msg 2714, Level 16, State 1, Procedure SYNC_SpreadMembers, Line 23
There is already an object named '#MM_SYNC_MEMBERS' in the database.
And here is my T-SQL code:
CREATE PROCEDURE SYNC_SpreadMembers
AS
BEGIN
BEGIN
-- Member
IF (OBJECT_ID('tempdb..#MM_SYNC_MEMBERS') IS NOT NULL)
DROP TABLE #MM_SYNC_MEMBERS;
-- Imported members
SELECT DISTINCT MemberInr INTO #MM_SYNC_MEMBERS FROM
(
SELECT DISTINCT DmInr AS MemberInr FROM MM_SYNC_EBOLIGWS WHERE NOT DmInr IS NULL
UNION
SELECT DISTINCT AmInr AS MemberInr FROM MM_SYNC_EBOLIGWS WHERE NOT AmInr IS NULL
) MemberHeap
;
DELETE #MM_SYNC_MEMBERS FROM #MM_SYNC_MEMBERS Sync INNER JOIN MM_Member Member ON Sync.MemberInr = Member.InteressentNr;
INSERT INTO MM_Member(InteressentNr) SELECT MemberInr FROM #MM_SYNC_MEMBERS;
END
-- Hardcoded members
DROP TABLE #MM_SYNC_MEMBERS;
SELECT DISTINCT InteressentNr AS MemberInr INTO #MM_SYNC_MEMBERS FROM MM_SYNC_HardcodedMemberRoles;
DELETE #MM_SYNC_MEMBERS FROM #MM_SYNC_MEMBERS Sync INNER JOIN MM_Member Member ON Sync.MemberInr = Member.InteressentNr;
INSERT INTO MM_Member(InteressentNr) SELECT MemberInr FROM #MM_SYNC_MEMBERS;
-- MemberRole
-- Area Managers
DELETE MM_MemberRole;
INSERT INTO MM_MemberRole(MemberSid, RoleSid)
SELECT DISTINCT Member.[Sid], (SELECT [Sid] FROM MM_Role WHERE Cipher LIKE 'AMA')
FROM MM_SYNC_EBOLIGWS Sync
INNER JOIN MM_Member Member ON Sync.AmInr = Member.InteressentNr
WHERE Sync.AmInr IS NOT NULL
;
-- Department Managers
INSERT INTO MM_MemberRole(MemberSid, RoleSid)
SELECT DISTINCT Member.[Sid], (SELECT Sid FROM MM_Role WHERE Cipher LIKE 'DM')
FROM MM_SYNC_EBOLIGWS Sync
INNER JOIN MM_Member Member ON Sync.DmInr = Member.InteressentNr
WHERE Sync.DmInr IS NOT NULL
;
-- Hardcoded Roles
INSERT INTO MM_MemberRole(MemberSid, RoleSid)
SELECT Member.Sid, Roles.Sid
FROM MM_SYNC_HardcodedMemberRoles HCR
INNER JOIN MM_Member Member ON HCR.InteressentNr = Member.InteressentNr
INNER JOIN MM_Role Roles ON HCR.RoleCipher = Roles.Cipher
;
END
GO
T-SQL is a very simple language - it basically compiles all of the code in the current scope/batch as soon as possible. At various times (such as when a new table is created) it will recompile the batch.
The error is actually being thrown when it does the recompile immediately after you first create the new temp table. At that point, when it tries to recompile the later statement that also tries to create a temp table with the same name, it produces the error.
It doesn't wait to see whether the normal flow of execution (including control flow) will prevent an error occurring when the statement is reached. E.g. this produces a similar error:
create table #Blah (ID int)
if 1 = 0
begin
create table #Blah (Foo int)
end
Even though we can look at it and know that no harm would actually occur
Msg 2714, Level 16, State 1, Line 4
There is already an object named '#Blah' in the database.
Since the table has the same columns in both inserts, why not just create the table once, and instead of dropping it:
TRUNCATE TABLE #MM_SYNC_MEMBERS
Temporary tables are tied to a connection. So when the connection is
dropped, the temporary table is dropped.
So it won't be dropped in the middle of the stored procedure.
This will be tied to the instance it is in, it could fit your needs:
DECLARE #TemporaryTable TABLE
(
id int,
name nvarchar(50)
)
Extra:
Maybe you could also have a look at CTE's as it may be a solution for your problem:
http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
why done you create structure of #MM_SYNC_MEMBERS globally and then you can delete or insert data in temp according to conditions.
EX-
create table #Temp
(name varchar(20))
IF(condtion1)
insert into temp (or delete)
else if(condition2)
insert to temp
.........

UPDATE with a stored procedure on SQL Server 2005

UPDATE users
SET field = my_sp()
in SQL Server 2005. Apparently I can't do this and have to use some form of EXEC. Can anyone help me out and let me know how to do this? This should be some easy rep.
To assign value you need to use sql function. it is impossible to assign value from stored procedure.
Here is link how to create it.
you need to write a scalar function that takes some parameters (or even zero) and returns what you need.
You could store the output of the stored procedure in a temp table, then use that temp table as the basis for your update. As an example, the code below assumes your proc returns a record set with two integers.
create table #t (
ColumnA int,
ColumnB int
)
insert into #t
(ColumnA, ColumnB)
exec my_sp
update u
set field = t.ColumnB
from users u
inner join #t t
on u.UserID = t.ColumnA
drop table #t

Resources