I have a stored procedure with takes 2 parameters (StudentID and CurrentSmester) as input and return me table with fields :
Course Code
Update Type
Update Id
This stored procedure is created by another team in my office. I can not modify it but at the same point I want to use it in my Webservice (which I am building for android) to make sure data remains consistent.
My requirement is to get :
Course Code
Update Type
Update Id
Course Title
Can I create another store procedure which will call that store procedure with parameters as I mentioned, make a join with course table to get course title too.
Is this possible ? If yes can you please guide me through its implementation.
Thanking You and Happy New Year !!
Create a new stored procedure , insert the results coming back from your existing stored procedure into a temp table, join your Course table with that temp table and you are good to go ,
something like this.....
CREATE PROCEDURE usp_NewProc
#StudentID INT ,
#CurrentSmester INT
AS
BEGIN
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
CourseCode [DataType],
UpdateType [DataType],
Update Id [DataType]
)
INSERT INTO #temp
EXEC existsting_proc #StudentID , #CurrentSmester
SELECT t.* , C.CourseTitle
FROM #temp t INNER JOIN CourseTable C on <join Condition>
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL
DROP TABLE #temp
END
You can insert the results from the STORED PROCEDURE into a temp table (table variable or temp table) and them select from that table and join onto the Courses table to retrieve the title.
SQL Fiddle DEMO
Example code
CREATE TABLE Courses(
CourseCode VARCHAR(50),
CourseName VARCHAR(250)
);
INSERT INTO Courses VALUES ('A','AA'), ('B','BB');
CREATE PROCEDURE OtherTeamsSP(
#StudentID INT,
#CurrentSmester INT
)
AS
SELECT 'A' CourseCode,
'FOO' UpdateType,
1 UpdateId;
CREATE PROCEDURE MyProcedure(
#StudentID INT,
#CurrentSmester INT
)
AS
CREATE TABLE #SPOutput(
CourseCode VARCHAR(50),
UpdateType VARCHAR(50),
UpdateId INT
)
INSERT INTO #SPOutput
EXEC OtherTeamsSP #StudentID, #CurrentSmester
SELECT *
FROM #SPOutput s INNER JOIN
Courses c ON s.CourseCode = c.CourseCode
DROP TABLE #SPOutput
Calling the new SP
EXEC MyProcedure 1,2
-- First Stored Procedure
CREATE PROCEDURE FirstSP
#MyFirstParam INT
AS
DECLARE #MyFirstParamValue INT
SELECT #MyFirstParamValue = #MyFirstParam * #MyFirstParam
RETURN (#MyFirstParamValue)
GO
-- Second Stored Procedure
CREATE PROCEDURE SecondSP
#SecondParam INT
AS
DECLARE #SecondParamValue INT
SELECT #SecondParamValue = #SecondParam * #SecondParam
RETURN (#SecondParamValue)
GO
-- Pass One Stored Procedure's Result as Another Stored Procedure's Parameter
DECLARE #FirstValue INT, #SeondValue INT
-- First SP
EXEC #FirstValue = FirstSP 5
-- Second SP
EXEC #SeondValue = SecondSP #FirstValue
SELECT #SeondValue SecondSP
GO
-- Clean up
DROP PROCEDURE FirstSP
DROP PROCEDURE SecondSP
GO
Related
I have created this stored procedure:
CREATE PROCEDURE [dbo].[zsp_MoveItemsToFolder]
(#IdListToMove IdListToMove READONLY,
#FolderId INT,
#UserId INT)
AS
BEGIN
DECLARE #Rowcount INT = 1;
WHILE (#Rowcount > 0)
UPDATE TOP (5000) dbo.SingleScannedItems --<-- define Batch Size in TOP Clause
SET MyListId = #FolderId
WHERE SingleScannedItemId IN (SELECT l.SingleScannedItemIds
FROM #IdListToMove l)
AND UserId = #UserId
SET #Rowcount = ##ROWCOUNT;
CHECKPOINT; --<-- to commit the changes with each batch
END
Prior to that I have created a user defined type in SQL like this:
CREATE TYPE [dbo].[IdListToMove] AS TABLE(
[SingleScannedItemIds] int NULL
);
And once I have imported the procedure into the C# LINQ the only parameters that I can see are FolderId and UserId.
However the #IdListToMove user defined type is not visible in the imported stored procedure :/...
So my question is: why is the user defined type not visible in the imported stored procedure (that is imported through the Entity Framework 6)
How do I fix this so that I can pass the list through C# into the stored procedure?
Can someone help me out?
Edit: here's the modified procedure with #Marc Gravel's suggestions:
ALTER PROCEDURE [dbo].[zsp_MoveItemsToFolder]
(#IdListToMove NVARCHAR(MAX),
#FolderId INT,
#UserId INT)
AS
BEGIN
DECLARE #Rowcount INT = 1;
WHILE (#Rowcount > 0)
UPDATE TOP (5000) dbo.SingleScannedItems --<-- define Batch Size in TOP Clause
SET MyListId = #FolderId
WHERE (EXISTS (SELECT 1
FROM dbo.SplitStringProduction(#IdListToMove,',') S1
WHERE SingleScannedItemId = S1.val))
AND UserId = #UserId
AND MyListId <> #FolderId
SET #Rowcount = ##ROWCOUNT;
CHECKPOINT; --<-- to commit the changes with each batch
END
I have a stored procedure which looks like following:
alter procedure [dbo].[zsp_deleteEndedItems]
(
#ItemIDList nvarchar(max)
)
as
delete from
SearchedUserItems
WHERE EXISTS (SELECT 1 FROM dbo.SplitStringProduction(#ItemIDList,',') S1 WHERE ItemID=S1.val)
The parameter IDList is passed like following:
124125125,125125125...etc etc
And the split string function look like following:
ALTER FUNCTION [dbo].[SplitStringProduction]
(
#string nvarchar(max),
#delimiter nvarchar(5)
) RETURNS #t TABLE
(
val nvarchar(500)
)
AS
BEGIN
declare #xml xml
set #xml = N'<root><r>' + replace(#string,#delimiter,'</r><r>') + '</r></root>'
insert into #t(val)
select
r.value('.','varchar(500)') as item
from #xml.nodes('//root/r') as records(r)
RETURN
END
This is supposed to delete all items from table "SearcheduserItems" under the IDs:
124125125 and 125125125
But for some reason after I do a select to check it out:
select * from SearchedUserItems
where itemid in('124125125','125125125')
The records are still there...
What am I doing wrong here? Can someone help me out?
As mentioned in the comments, a different option would be to use a table type parameter. This makes a couple of assumptions (some commented), however, should get you on the right path:
CREATE TYPE dbo.IDList AS TABLE (ItemID int NOT NULL); --Assumed int datatype;
GO
ALTER PROC dbo.zsp_deleteEndedItems #ItemIDList dbo.IDList READONLY AS
DELETE SUI
FROM dbo.SearchedUserItems SUI
JOIN #ItemIDList IDL ON SUI.ItemID = IDL.ItemID;
GO
--Example of usage
DECLARE #ItemList dbo.IDList;
INSERT INTO #ItemList
VALUES(123456),(123457),(123458);
EXEC dbo.zsp_deleteEndedItems #ItemList;
GO
In regards to the question of an inline table value function, one such example is the below, which I quickly wrote up, that provides a tally table of the next 1000 numbers:
CREATE FUNCTION dbo.NextThousand (#Start int)
RETURNS TABLE
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)
)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 + #Start AS I
FROM N N1 --10
CROSS JOIN N N2 --100
CROSS JOIN N N3; --1,000
GO
The important thing about an iTVF is that it has only one statement, and that is the RETURN statement. Declaring the table as a return type variable, inserting data into it, and returning that variable turns it into a multi-line TVF; which perform far slower.
I have a database which stores information about a library (books, authors & categories).
But I can't get my stored procedure to work for inserting data. The stored procedure itself executes fine, but when I perform a test, it simply doesn't add anything to the database. Can anyone see what I'm missing?
This is my stored procedure (for category):
USE MyLibrary
GO
IF EXISTS (SELECT 1 FROM sysobjects WHERE name = 'CategoryInsert' AND TYPE = 'P')
BEGIN
DROP PROC CategoryInsert
END
GO
CREATE PROCEDURE CategoryInsert
(
#Id int out,
#Name nvarchar(255),
#InsertedBy nvarchar(120),
#InsertedOn datetime
)
AS
DECLARE #CurrentId int
SELECT #CurrentId = Id FROM Category WHERE lower(#Name) = lower(#Name)
IF #CurrentId IS NOT NULL
BEGIN
SET #Id = -100
RETURN
END
INSERT INTO Category
(
Name,
InsertedBy,
InsertedOn
)
VALUES
(
#Name,
#InsertedBy,
#InsertedOn
)
SET #Id = SCOPE_IDENTITY()
GO
This is my test:
USE MyLibrary
GO
DECLARE #NewId int
DECLARE #date datetime
SET #date = getdate()
EXEC CategoryInsert #NewId, 'Testing', 'AL', #date
SELECT #NewId
GO
This line:
SELECT #CurrentId = Id FROM Category WHERE lower(#Name) = lower(#Name)
IF #CurrentId IS NOT NULL
The equality check will always return true because you're essentially comparing WHERE 1 = 1, which means that #CurrentID will always have a value and thus your stored procedure will always return before the INSERT happens.
I have function for combobox.
ALTER FUNCTION [FN.USERNew]
(
#USER_ID INT
)
RETURNS TABLE
AS
RETURN
(
Select [USER_NAME] , username_Id From USER
WHERE USER_ID=#USER_ID
)
GO
I try to use above function in my stored procedure like below.
However, I get an error
Cannot Find either column"dbo" or the user -defined function or aggregate "dbo.FN.USERNew", or name is ambigous."
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
DBO.FN.USERNew(USER_ID) AS PROBLEMHERE
FROM PRODUCT_TABLE
WHERE PRODUCT_ID=#PRODUCT_ID
END
So why i can not use my function in my stored procedure ?
You have to continue to quote the name using [] or "" because . is used to separate name parts:
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
DBO.[FN.USERNew](USER_ID) AS PROBLEMHERE
FROM PRODUCT_TABLE
WHERE PRODUCT_ID=#PRODUCT_ID
END
See Database Identifiers.
However, this is a table valued function - which would more normally be used in the FROM clause (possibly via APPLY) - I'm not sure that SQL Server will let you use it in the SELECT clause since it can return multiple columns and rows. I think you may want:
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
ft.* AS PROBLEMHERE
FROM PRODUCT_TABLE pt
CROSS APPLY DBO.[FN.USERNew](pt.USER_ID) ft
WHERE pt.PRODUCT_ID=#PRODUCT_ID
END
I was wondering how I can pass either an ArrayList, List<int> or StringBuilder comma delimited list to a stored procedure such that I find a list of IDs using IN():
#myList varchar(50)
SELECT *
FROM tbl
WHERE Id IN (#myList)
In C# I am currently building the list as a string which is comma delimeted; however when using nvarchar(50) for example, as the type for the param in the stored procedure - I get an error as it can't convert '1,2,3' to int which it expects between the IN().
Any ideas? Much appreciated.
Pete
You could use a User Defined function such as
CREATE function [dbo].[csl_to_table] ( #list nvarchar(MAX) )
RETURNS #list_table TABLE ([id] INT)
AS
BEGIN
DECLARE #index INT,
#start_index INT,
#id INT
SELECT #index = 1
SELECT #start_index = 1
WHILE #index <= DATALENGTH(#list)
BEGIN
IF SUBSTRING(#list,#index,1) = ','
BEGIN
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
SELECT #start_index = #index + 1
END
SELECT #index = #index + 1
END
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
RETURN
END
Which accepts an nvarchar comma separated list of ids and returns a table of those ids as ints. You can then join on the returned table in your stored procedure like so -
DECLARE #passed_in_ids TABLE (id INT)
INSERT INTO #passed_in_ids (id)
SELECT
id
FROM
[dbo].[csl_to_table] (#your_passed_in_csl)
SELECT *
FROM
myTable
INNER JOIN
#passed_in_ids ids
ON
myTable.id = ids.id
In SQL 2008 there are table-valued-parameters, that make a friendly alternative to parsing CSV; see here for an example.
Otherwise, another option is xml - the xml data type in SQL Server allows you to read this pretty easily (although it takes more transfer bytes).