So I have been working on simple procedure for school that asks me to:
(Create a stored procedure called UpdateProduct that takes in a required Product ID parameter and optionally any other one or more fields in the Product table. Then the proc will update any fields passed in but leave any other fields as they were.
If executed like this: UpdateProduct #productID = 1, #name = ‘Steel Ball Bearing’; Only the name should change, all other fields should still contain the value there before the procedure
was called)
This is what I have but still I cant seem to get it to work properly. I am going nuts because I have been trying to figure this out for several days. Any help pointing out my mistake would be awesome.
USE AdventureWorks2012
GO
CREATE PROC UpdateProduct2
#ProductID INT ,
#Name nvarchar (50)= ISNULL,
#ProductNumber nvarchar (25) =ISNULL,
#Color nvarchar (15)=ISNULL
AS
BEGIN
UPDATE [Production].[Product]
SET
Name = ISNULL (#Name,Name),
ProductNumber = ISNULL (#ProductNumber,ProductNumber),
Color = ISNULL (#Color, Color)
WHERE #Name=Name
END
I think your where clause should be:
WHERE ProductID = #ProductID;
rather than
WHERE #Name=Name
Also you need to use NULL rather than ISNULL to set the parameter defaults:
CREATE PROC UpdateProduct2
#ProductID int,
#Name nvarchar(50) = NULL,
#ProductNumber nvarchar(25) = NULL,
#Color nvarchar(15) = NULL
AS
BEGIN
UPDATE [Production].[Product]
SET Name = ISNULL (#Name,Name),
ProductNumber = ISNULL (#ProductNumber,ProductNumber),
Color = ISNULL (#Color, Color)
WHERE ProductID = #ProductID;
END
EDIT
To answer the question about specifying NULL as the default, yes there is a reason, it allows you to call the procedure without passing the parameter.
Take the following two procedures:
CREATE PROCEDURE dbo.P1 #p1 VARCHAR(20), #p2 VARCHAR(20)
AS
BEGIN
SELECT P1 = #p1, P2 = #p2;
END;
GO
CREATE PROCEDURE dbo.P2 #p1 VARCHAR(20) = NULL, #p2 VARCHAR(20) = NULL
AS
BEGIN
SELECT P1 = #p1, P2 = #p2;
END;
The first using no default, and the latter with NULL as the default. The only way to call the first procedure is to send all parameters, e.g.
EXECUTE dbo.p1;
EXECUTE dbo.p1 #P2 = 'TEST';
EXECUTE dbo.p1 #P1 = 'TEST';
Will generate the following errors:
Msg 201, Level 16, State 4, Procedure P1, Line 0
Procedure or function 'P1' expects parameter '#p1', which was not supplied.
Msg 201, Level 16, State 4, Procedure P1, Line 0
Procedure or function 'P1' expects parameter '#p1', which was not supplied.
Msg 201, Level 16, State 4, Procedure P1, Line 0
Procedure or function 'P1' expects parameter '#p2', which was not supplied.
Whereas this:
EXECUTE dbo.p2;
EXECUTE dbo.p2 #P2 = 'TEST';
EXECUTE dbo.p2 #P1 = 'TEST';
Will generate:
P1 P2
NULL NULL
P1 P2
NULL TEST
P1 P2
TEST NULL
Related
I get 'A TOP or FETCH clause contains an invalid value' this error
"
Msg 1014, Niveau 15, État 1, Procédure dbo.sp_contacts_getcontacts, Ligne 24 [Ligne de départ du lot 0]
A TOP or FETCH clause contains an invalid value. "
I want to get contacts using stored procedure , this is the code of the SP
( #Id uniqueidentifier = NULL,
#role nvarchar(max) = NULL,
#IdCompany uniqueidentifier = NULL,
#Active bit = 0,
#Page int = NULL,
#PerPage int = NULL,
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Insert statements for procedure here
SELECT *
FROM [dbo].[Contacts]
LEFT JOIN [dbo].[Companies]
ON Contacts.[IdCompany] = Companies.[IdCompany]
WHERE
(#Id is null or #Id = [IdContact])
AND (#role is null or #role=contacts.[Role])
AND (#IdCompany is null or #IdCompany = [IdCompany])
AND (#Active = 0 or #Active = [Active])
ORDER BY [IdContact] OFFSET ((#Page - 1) * #PerPage) ROWS FETCH NEXT #PerPage ROWS ONLY
END
I could be misunderstanding your question.
If you want to grab the results from that select, you'll need a table variable that matches the output of the sproc to Insert Into.
DECLARE #someTable TABLE(
/* Whatever the output is of the sproc */
)
INSERT INTO #someTable
EXEC #return_value = dbo.nameOfYourSproc
You could also try creating a temp table from the results
INSERT INTO #someTable
EXEC #return_value = dbo.nameOfYourSproc
Although, my recommendation is to turn that SPROC into a table-valued function.
The code was correct , i just did not insert values for page and perpage this way it show the error 'FETCH...'
I am getting this error
Msg 201, Level 16, State 4, Procedure sp_GetAllAirports, Line 0 [Batch Start Line 2]
Procedure or function 'sp_GetAllAirports' expects parameter '#AirportID', which was not supplied."
When I run
EXEC sp_GetAllAirports
The following is my stored procedure which shows #AirportID, what could be the issue?
IF OBJECT_ID('sp_GetAllAirports', 'P') IS NOT NULL
DROP PROCEDURE [dbo].[sp_GetAllAirports]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_GetAllAirports]
#AirportID INT,
#ICAOCode VARCHAR(4) NULL,
#AirportName VARCHAR(MAX),
#City VARCHAR(MAX),
#Lat DECIMAL(8,3),
#Long DECIMAL (11,3),
#Elevation INT,
#Country NVARCHAR(MAX)
AS
BEGIN TRANSACTION
BEGIN TRY
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
--SELECT * FROM tbl_Airports ORDER BY AirportID ASC
SELECT
AirportID, ICAOCode, AirportName, City,
Latitude, Longitude, Elevation, CountryFK
FROM
tbl_Airports
LEFT JOIN
tbl_Countries ON CountryID = tbl_Airports.CountryFK
WHERE
CountryID = tbl_Airports.CountryFK
ORDER BY
AirportID
END TRY
BEGIN CATCH
DECLARE #ErMessage NVARCHAR(MAX),
#ErSeverity INT,
#ErState INT
SELECT
#ErMessage = ERROR_MESSAGE(),
#ErSeverity = ERROR_SEVERITY(),
#ErState = ERROR_STATE()
IF ##TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
END
RAISERROR(#ErMessage, #ErSeverity, #ErState)
END CATCH
IF ##TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION
END
GO
Your stored procedure is defined to expect arguments (AirportID, ICAOCode, AirportName, City, Lat, Long, Elevation and Country):
CREATE PROCEDURE [dbo].[sp_GetAllAirports]
#AirportID INT,
#ICAOCode VARCHAR(4) NULL,
#AirportName VARCHAR(MAX),
#City VARCHAR(MAX),
#Lat DECIMAL(8,3),
#Long DECIMAL (11,3),
#Elevation INT ,
#Country NVARCHAR(MAX)
AS
...
However, it doesn't use any of them. So you probably just need to remove them:
CREATE PROCEDURE [dbo].[sp_GetAllAirports]
AS
...
Alternatively, make sure the arguments are used in the SP (so it makes sense to expect arguments) and pass values accordingly (sp_GetAllAirports 1234) e.g.:
CREATE PROCEDURE [dbo].[sp_GetAllAirports]
#AirportID INT
AS
....
SELECT AirportID, ICAOCode, AirportName, City, Latitude, Longitude, Elevation, CountryFK
FROM tbl_Airports
LEFT JOIN tbl_Countries ON CountryID = tbl_Airports.CountryFK
WHERE CountryID = tbl_Airports.CountryFK
AND AirportID = #AirportID -- Using first argument here
ORDER BY AirportID
....
Or, finally, give the arguments default values, e.g:
CREATE PROCEDURE [dbo].[sp_GetAllAirports]
#AirportID INT = NULL,
#ICAOCode VARCHAR(4) = 'FOO',
...
AS
...
That way you won't have to explicitly pass any argument values. However, you'll still need to use the arguments to having the arguments make sense in the first place.
I created a custom table type
Create type dbo.InsertPatient as table
(SSN Int,
LastUpdated Datetime,
PatientId varchar(50),
McdNo varchar(50),
mcrno varchar(50)
)
GO
I tried to declare an input parameter using this type
Create PROCEDURE [dbo].[proc_PatientDt_Insert]
(
#PatientTable InsertPatient READONLY,
#FacilityID int,
#IsDeleted bit = 0
)
AS
BEGIN
SET NOCOUNT OFF
DECLARE #Err int
IF(#IsDeleted = 1)
BEGIN
DELETE FROM [Patient]
WHERE LTRIM(RTRIM([Patientid])) = LTRIM(RTRIM(#PatientTable.PatientId))
AND FacilityID = #FacilityID
RETURN
END
SET #Err = ##Error
RETURN #Err
END
When I try to execute, I get this error
Msg 137, Level 16, State 1, Procedure proc_PatientDt_Insert, Line 18
Must declare the scalar variable "#PatientTable".
The error message is a little misleading, but it's because you're trying to use a Table Varaible as if it was a plain old scalar variable. Table variables work more or less like tables. While it's possible the variable will only have one row, it could have 100. You need to SELECT and/or JOIN from that variable. If you only ever expect to have 1 row, or want to take an arbitrary first row and ignore others, you could change
LTRIM(RTRIM([Patientid])) = LTRIM(RTRIM(#PatientTable.PatientId)) AND FacilityID=#FacilityID
to
LTRIM(RTRIM([Patientid])) = LTRIM(RTRIM(SELECT TOP 1 PatientId FROM #PatientTable)) AND FacilityID=#FacilityID
But you'd probably be best off doing:
DELETE p
FROM Patient p
INNER JOIN #PatientTable p2
ON LTRIM(RTRIM(p.PatientId) = LTRIM(RTRIM(p2.PatientId)
WHERE p.FacilityId = #FacilityId
I have this stored procedure:
create proc Sponsors.GetLightBoxAd
(
#SponsorID varchar(30),
#ADIDOut varchar(30) OUTPUT,
#UserID varchar(30),
#ProjectID varchar(50),
#PlatformID int
)
as
begin
SELECT TOP 1 #ADIDOut = AD.ADID --my output. AD.ADID is a varchar(30) column
FROM Sponsors.AD
WHERE AD.Active = 1 and AD.SponsorID = #SponsorID
ORDER by NEWID() -- I want the first one picked at random
IF ISNULL(#ADIDOut,-1) != -1 --if the result set wasn't null, run some update queries with the result
BEGIN --These queries do not have output variables.
EXEC Sponsors.proc1 #ADIDOut, #SponsorID
EXEC Projects.proc2 #ProjectID,#ADIDOut,#UserID,#PlatformID
END --end the if
end --end the proc
go
This should return either a null value or a varchar.
However when I try to execute the query, SSMS auto-generates this code for me to run the query:
USE [MyDB]
GO
DECLARE #return_value int, --Why is this here???
#ADIDOut varchar(30) -- this should be my only output
EXEC #return_value = [Sponsors].[GetLightBoxAd]
#SponsorID = N'Alienware',
#ADIDOut = #ADIDOut OUTPUT,
#UserID = N'127.0.0.1',
#ProjectID = N'TestProject',
#PlatformID = 1
SELECT #ADIDOut as N'#ADIDOut'
SELECT 'Return Value' = #return_value --why is this here?
GO
And then it gives me an error because it appears to try to convert the result of ADIDOut into an int... Why is there an int #Return_Value variable and why is it trying to put my actual OUTPUT result into it?
The error was in this line:
IF ISNULL(#ADIDOut,-1) != -1
It seems since I put just -1 without quotes as the comparison, sql reads this as an integer and cannot compare it to a nullable string so the error is raised. Putting the -1's into quotes fixes the error and the query runs. Thanks for the help!
Can we return null value from stored procedure. i dont want to use collase or isnull. I want to capture NULL at the frontend. Is it possible ?
Edit:
I am using Sql Server 2005
eg. where i want to use
CREATE PROCEDURE [Authentication].[spOnlineTest_CheckLogin]
#UserName NVARCHAR(50)
AS
BEGIN TRY
BEGIN TRAN
COMMIT TRAN
RETURN NULL
END TRY
Error
The 'spOnlineTest_CheckLogin' procedure attempted to return a status of NULL, which is not allowed. A status of 0 will be returned instead.
Msg 0, Level 11, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
No, the return type of a stored procedure is INT and it cannot be null.
use an output parameter, example
CREATE PROCEDURE Test
#UserName NVARCHAR(50), #Status int output
AS
BEGIN TRY
BEGIN TRAN
COMMIT TRAN
set #Status = null
END TRY
begin catch
end catch
go
then call it like this
declare #s int
set #s =5
exec Test'bla',#s output
select #s --will be null
You can think of a proc like follows. Let me first set the context. We might have a table Table1(id int, name varchar(2), Address varchar(2)) and want to get the id and if not found, it will be null. So we might write a proc like the following:
CREATE PROCEDURE GetId
#Name VARCHAR(50), #Status int output
AS
BEGIN TRY
set #Status = null
select #Status = id from Table1 where name=#name
This will work for you.