How to pass multiple values for a column in sql Stored Procedure? - sql

i have two tables, such as
Queue
QueueID
LogParameters
QueueParameters
QueueParametersID
QueueID
LogParametersKey
LogParametersValue
I have to write SP inorder to make an entry in both the tables,
LogParameterKey and LogParameterValue may contains multiple values but the QueueID for each values should be same and QueueParameterID could be different.
**QueueID** **LogParameters**
1 AA
**QueueParametersID** **QueueID** **LogParametersKey** **LogParametersValue**
1 1 FirstName Mohammad
2 1 LastName Salman
3 1 Age 17
How do i pass multiple values for LogParameterKey and LogParameterValue?.. Someone suggested me to use Array for this... Is there's any other way?
CREATE Procedure AddQueue
#LogParameters NVARCHAR(255)
#AuditParameters AS AuditParameter READONLY,-- UserDefinedTable
AS
SET NOCOUNT ON;
BEGIN
DECLARE #QueueID BIGINT
EXECUTE dbo.procInsertQueue
#LogParameters = #LogParameters,
#QueueID = #QueueID OUTPUT
DECLARE #GetQueueID BIGINT = (SELECT QueuesID FROM Queues WHERE LogParameters= #LogParameters
DECLARE #AuditQueueParametersID BIGINT
DECLARE #TempTable TABLE(
ParameterKey NVARCHAR(255),
ParameterValue NVARCHAR(255),
AuditQueuesID BIGINT)
INSERT INTO #TempTable(ParameterKey,ParameterValue,QueuesID)
SELECT ParameterKey,ParameterValue,#GetQueueID FROM #AuditParameters
DECLARE #LogParameterKey NVARCHAR(255) = (SELECT ParameterKey FROM #TempTable WHERE QueuesID = #GetQueueID)
DECLARE #LogParameterValue NVARCHAR(255) = (SELECT ParameterValue FROM #TempTable WHERE QueuesID = #GetQueueID)
EXECUTE dbo.procAddQueueParameters
#AuditQueueID = #GetQueueID
#LogParametersKey = #LogParametersKey,
#LogParametersValue = #LogParametersValue,
#QueueParametersID = #QueueParametersID OUTPUT
END
END

1. Use User-Defined Table Types
https://technet.microsoft.com/en-us/library/bb522526(v=sql.105).aspx
2. Generate xml string and parse in SP
3.Use temp table
CREATE TABLE #Input
(
QueueParametersID ..
QueueID ..
LogParametersKey ..
LogParametersValue ..
)
--INSERT VALUES
EXEC dbo.YouSP
IN SP use table #Input

Related

Using IN operator with a variable in SAP HANA

I am trying to use a variable as input for a WHERE condition having an IN clause using SAP HANA.
For example:
DO
BEGIN
DECLARE a VARCHAR(100) = '1000,1001';
DECLARE b NVARCHAR(100) ARRAY = ARRAY('1000','1001');
DECLARE c TABLE (valuelist NVARCHAR(100));
--SELECT '1001' INTO valuelist FROM :c;
--:c.INSERT('1001','1000');
DECLARE e NVARCHAR(100) = ' ''1000'',''1001'' ';
DECLARE f NVARCHAR(100) = '"STATIONID" IN (''1000'',''1001'')';
select
STATIONID
from MY_TABLE
where STATIONID IN ('1000','1001') -- working fine, but want to use a variable here
-- where STATIONID IN (:a)
-- where STATIONID IN (:b)
-- where STATIONID IN :c
-- where :f
order by STATIONID;
END
However, all my attempts, you can see some of them above, do fail when having multiple values in my condition. STATIONID really is a string field.
Any hints on how to do this?
Finally I figured out how I can use a variable array together with a variable table by using UNNEST. This is working just fine:
DO
BEGIN
DECLARE STATION_TMP_ARRAY NVARCHAR(10) ARRAY = ARRAY('1000','1001','1002','1003','1004');
DECLARE STATION_TMP_TABLE TABLE ("tmp_stationid" NVARCHAR(10)) = UNNEST(:STATION_TMP_ARRAY) AS ("tmp_stationid");
select
STATIONID
from MY_TABLE
where "STATIONID" IN (SELECT "tmp_stationid" FROM :STATION_TMP_TABLE)
order by STATIONID;
END

SQL dynamic columns and Update multiple columns

I have a table UserPermission which has a number of columns of TINYINT type. e.g Read, Write, Update, Delete, Access etc.
I get three parameters in the stored procedure: #UserId, #ColNames, #ColValues where #ColNames and #ColValues are comma separated values.
How can I insert or update the table row (if already exists) with the passed column names and corresponding values.
I try to write the dynamic query which runs fine for INSERT but I was unable to write the UPDATE query dynamically with each column and its value to be concatenate.
Any response would be appreciated
Thanks in advance.
This is a somewhat dirty way to do what you require. However, if you create the following Stored Procedure:
CREATE FUNCTION [dbo].[stringSplit]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
You can then use that Procedure to join the data together:
DECLARE #TotalCols INT
DECLARE #TotalVals INT
SET #TotalCols = (
SELECT COUNT(ID) AS Total
FROM dbo.stringSplit('department, teamlead', ',')
);
SET #TotalVals = (
SELECT COUNT(ID) AS Total
FROM dbo.stringSplit('IT, Bob', ',')
);
IF #TotalCols = #TotalVals
BEGIN
IF OBJECT_ID('tempdb..#temptable') IS NOT NULL
DROP TABLE #temptable
CREATE TABLE #temptable (
ColName VARCHAR(MAX) NULL
,ColValue VARCHAR(MAX) NULL
)
INSERT INTO #temptable
SELECT a.DATA
,b.DATA
FROM dbo.stringSplit('department, teamlead', ',') AS a
INNER JOIN dbo.stringSplit('IT, Bob', ',') AS b ON a.Id = b.Id
SELECT *
FROM #temptable;
END
It's not very efficient, but it will bring you the desired results.
You can then use the temp table to update, insert and delete as required.
Instead of having a comma delimited list I would create a separate parameter for each Column and make its default value to NULL and in the code update nothing if its null or insert 0. Something like this....
CREATE PROCEDURE usp_UserPermissions
#UserID INT
,#Update INT = NULL --<-- Make default values NULL
,#Delete INT = NULL
,#Read INT = NULL
,#Write INT = NULL
,#Access INT = NULL
AS
BEGIN
SET NOCOUNT ON;
Declare #t TABLE (UserID INT, [Update] INT,[Read] INT
,[Write] INT,[Delete] INT,[Access] INT)
INSERT INTO #t (Userid, [Update],[Read],[Write],[Delete],[Access])
VALUES (#UserID , #Update , #Read, #Write , #Delete, #Access)
IF EXISTS (SELECT 1 FROM UserPermission WHERE UserID = #UserID)
BEGIN
UPDATE up -- Only update if a value was provided else update to itself
SET up.[Read] = ISNULL(t.[Read] , up.[Read])
,up.[Write] = ISNULL(t.[Write] , up.[Write])
,up.[Update] = ISNULL(t.[Update] , up.[Update])
,up.[Delete] = ISNULL(t.[Delete] , up.[Delete])
,up.[Access] = ISNULL(t.[Access] , up.[Access])
FROM UserPermission up
INNER JOIN #t t ON up.UserID = t.UserID
END
ELSE
BEGIN
-- if already no row exists for that User add a row
-- If no value was passed for a column add 0 as default
INSERT INTO UserPermission (Userid, [Update],[Read],[Write],[Delete],[Access])
SELECT Userid
, ISNULL([Update], 0)
, ISNULL([Read], 0)
, ISNULL([Write], 0)
, ISNULL([Delete], 0)
, ISNULL([Access], 0)
FROM #t
END
END

Iterate through values of a table variable in a stored procedure

I am writing a stored proc as follows:
CREATE PROCEDURE ListByOrderRequestId
#EntityId int,
#EntityTypeId varchar(8)
AS
BEGIN
SET NOCOUNT ON;
Declare #IDS table(OrderRequestId int)
INSERT INTO #IDS
SELECT OrderRequestTaskId
FROM OrderRequestTask ORT WITH (NOLOCK)
WHERE ORT.OrderRequestId = #EntityId
SELECT N.EntityNoteId AS Id,
N.UpdateDate AS DateStamp,
N.EntityNoteText,
N.EntityId,
N.EntityNoteTypeId,
N.EntityTypeId
FROM EntityNote N
WHERE (N.EntityId = #EntityId AND N.EntityTypeId ='ORDREQ')
*OR(N.EntityId = #IDS VAL1 AND N.EntityTypeId ='TASK')
OR(N.EntityId = #IDS VAL2 AND N.EntityTypeId ='TASK')*
END
The table #IDS can have 0 or 1 or more values in it. I want to loop through the values in #TDS and create the where clause above accordingly. Please help me.
As opposed to looping through the table, you could just use it in your where clause like this:
Select * From {Your Table} Where ID in (Select OrderRequestId From IDS)
This is much faster than looping.

How can I call and get back the results of an SP from another Stored Procedure

I have this stored procedure:
CREATE PROCEDURE [dbo].[sp_get_correct_responses]
#QuestionUId UNIQUEIDENTIFIER
AS
BEGIN
...
-- This is the last part of the SP. I need to use the output
-- value of #AnswerGridCorrect in the calling SP
SELECT #AnswerGridCorrect = Correct
FROM Concatenated
WHERE RowNumber = ColumnCount
END
How can I call the stored procedure from another stored procedure, pass it the #QuestionUId parameter and put the returned variable #AnswerGridCorrect into a variable declared in the calling procedure?
Update: Here's the proposed answer:
CREATE PROCEDURE [dbo].[sp_get_correct_responses]
#QuestionUId UNIQUEIDENTIFIER,
#output VARCHAR(20) output
AS
BEGIN
select #QuestionUId
DECLARE #AnswerGridCorrect VARCHAR(20)
DECLARE #QuestionId int;
SELECT #QuestionId = QuestionId
FROM dbo.Question
Where QuestionUId = #QuestionUId;
Select #questionId;
WITH Partitioned AS (
SELECT ROW_NUMBER() OVER (PARTITION BY QuestionId ORDER BY AnswerId ASC) AS RowNumber,
COUNT(1) OVER (PARTITION BY QuestionId) AS ColumnCount,
CONVERT(VARCHAR(MAX), Correct) AS Correct
FROM dbo.Answer
WHERE [QuestionId] = #QuestionId
),
Concatenated AS (
SELECT RowNumber, ColumnCount, Correct FROM Partitioned WHERE RowNumber = 1
UNION ALL
SELECT P.RowNumber,
P.ColumnCount,
C.Correct + P.Correct AS Correct
FROM Partitioned P
INNER JOIN Concatenated C
ON P.RowNumber = C.RowNumber + 1
)
SET #output = (SELECT Correct
FROM Concatenated
WHERE RowNumber = ColumnCount)
RETURN
END
You could have a temp table in the other stored procedure and populate it with the results of this one:
INSERT INTO #table
Exec sp_get_correct_responses #QuestionUId
The other way would be to modify sp_get_correct_responses to produce an output as you are expecting only one value.
CREATE PROCEDURE [dbo].[sp_get_correct_responses]
#QuestionUId UNIQUEIDENTIFIER,
#output VARCHAR(20) output
AS
BEGIN
...
-- This is the last part of the SP. I need to use the output
-- value of #AnswerGridCorrect in the calling SP
SELECT #output = Correct
FROM Concatenated
WHERE RowNumber = ColumnCount
RETURN
END
And in your other SP:
DECLARE #output VARCHAR(20)
EXEC sp_get_correct_responses
#QuestionUId,
#output output
SELECT #output
You can make one table variable in parent SP and insert result of child SP in that like below :
DECLARE #TempTable TABLE(AnswerGridCorrect INT)
INSERT INTO #TempTable
EXEC [dbo].[sp_get_correct_responses] #QuestionUId

Adding column to a resultset in stored procedure

I'm working on SP, I want to add a column to a resultset. Normally this would not be a proble, but here I'm using an Exec to fill one temp-table. To that temp-table I want to add one column.
Some prestuff that puts data in one of the temp-tables with some conditions
declare #RowCount int
set #RowCount = 1
create table #Temp_HS (row int IDENTITY (1, 1) NOT NULL, h varchar(30))
Create table #tmpS (K varchar(100),
U varchar(100), Counter int, H varchar(100))
--Puts data in one temp_table with employees
insert into #Temp_HS (h)
select Login from database.dbo.Users
where Old <> 1
and TC in ('A_1', 'A_2')
and Login not in ('Steve', 'Peter', 'Gabs')
--Declaring my counter here, it sets the MaxRow which is 19 in this case
declare #Counter int
set #Counter = (select Max(row) from #Temp_HS)
select * from #Temp_HS
-- Looping, That my RowCount must be less or Equal to Counter which is 19.
while #RowCount <= #Counter
begin
Set User which was originally from the Database Login which is declared as H in the temp table.
declare #user varchar(30)
select #user = h from #Temp_HS where row = #RowCount
Here comes the tricky part, this is the Stored procedure that inserts 3 columns into a temp
table, here I want to add one colum which in this case is h from Temp_HS to the resultset.
INSERT INTO #tmpS
EXEC Database.dbo.getListCount #user,
param,
param,
param,
'something',
param
set #RowCount = #RowCount +1
end
drop table #Temp_HS
If you need any further information just ask! :)
Basically I want to add one more column to the results of my Exec SP that inserts the result into a temp_table
INSERT INTO .. EXEC requires that the table you are inserting into already exists, e.g.
-- Given this preexisting proc
CREATE PROC dbo.getListCount #user INT, -- other params
AS
SELECT #User as Col1,
'SomeVarChar' as Col2
FROM [SomeTable];
-- In your code, create the temp table to hold the data
CREATE TABLE #tmpS
(
Col1 INT,
Col2 NVARCHAR(100),
NewColumnH VARCHAR(30) -- Add the additional column up front
-- etc.
);
This is called as
INSERT INTO #tmpS(Col1, Col2)
EXEC dbo.getListCount, #User;
If you then need to do do further processing on your temp table, do this after the PROC call:
UPDATE ts
SET NewColumnH = t.h
FROM #tmpS ts INNER JOIN #Temp_HS th on th.row = #RowCount;
Actually inner join doesnt work as desireed on temp tables that is why I used this solution. Since I already had #User in a variable I choose to do this update instead.
UPDATE ts
SET NewColumnH = #User
FROM #tmpS ts
where ts.Column is null