Procedure or function !!! has too many arguments specified - sql

I am developing my very first stored procedure in SQL Server 2008 and need advice concerning the errors message.
Procedure or function xxx too many arguments specified
which I get after executing the stored procedure [dbo].[M_UPDATES] that calls another stored procedure called etl_M_Update_Promo.
When calling [dbo].[M_UPDATES] (code see below) via right-mouse-click and ‘Execute stored procedure’ the query that appears in the query-window is:
USE [Database_Test]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[M_UPDATES]
SELECT 'Return Value' = #return_value
GO
The output is
Msg 8144, Level 16, State 2, Procedure etl_M_Update_Promo, Line 0
Procedure or function etl_M_Update_Promo has too many arguments specified.
QUESTION: What does this error message exactly mean, i.e. where are too many arguments? How to identify them?
I found several threads asking about this error message, but the codes provided were all different to mine (if not in another language like C# anyway). So none of the answers solved the problem of my SQL query (i.e. SPs).
Note: below I provide the code used for the two SPs, but I changed the database names, table names and column names. So, please, don’t be concerned about naming conventions, these are only example names!
(1) Code for SP1 [dbo].[M_UPDATES]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ M_UPDATES] AS
declare #GenID bigint
declare #Description nvarchar(50)
Set #GenID = SCOPE_IDENTITY()
Set #Description = 'M Update'
BEGIN
EXEC etl.etl_M_Update_Promo #GenID, #Description
END
GO
(2) Code for SP2 [etl_M_Update_Promo]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
as
declare #start datetime = getdate ()
declare #Process varchar (100) = 'Update_Promo'
declare #SummeryOfTable TABLE (Change varchar (20))
declare #Description nvarchar(50)
declare #ErrorNo int
, #ErrorMsg varchar (max)
declare #Inserts int = 0
, #Updates int = 0
, #Deleted int = 0
, #OwnGenId bit = 0
begin try
if #GenId = 0 begin
INSERT INTO Logging.dbo.ETL_Gen (Starttime)
VALUES (#start)
SET #GenId = SCOPE_IDENTITY()
SET #OwnGenId = 1
end
MERGE [Database_Test].[dbo].[Promo] AS TARGET
USING OPENQUERY( M ,'select * from m.PROMO' ) AS SOURCE
ON (TARGET.[E] = SOURCE.[E])
WHEN MATCHED AND TARGET.[A] <> SOURCE.[A]
OR TARGET.[B] <> SOURCE.[B]
OR TARGET.[C] <> SOURCE.[C]
THEN
UPDATE SET TARGET.[A] = SOURCE.[A]
,TARGET.[B] = SOURCE.[B]
, TARGET.[C] = SOURCE.[c]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([E]
,[A]
,[B]
,[C]
,[D]
,[F]
,[G]
,[H]
,[I]
,[J]
,[K]
,[L]
)
VALUES (SOURCE.[E]
,SOURCE.[A]
,SOURCE.[B]
,SOURCE.[C]
,SOURCE.[D]
,SOURCE.[F]
,SOURCE.[G]
,SOURCE.[H]
,SOURCE.[I]
,SOURCE.[J]
,SOURCE.[K]
,SOURCE.[L]
)
OUTPUT $ACTION INTO #SummeryOfTable;
with cte as (
SELECT
Change,
COUNT(*) AS CountPerChange
FROM #SummeryOfTable
GROUP BY Change
)
SELECT
#Inserts =
CASE Change
WHEN 'INSERT' THEN CountPerChange ELSE #Inserts
END,
#Updates =
CASE Change
WHEN 'UPDATE' THEN CountPerChange ELSE #Updates
END,
#Deleted =
CASE Change
WHEN 'DELETE' THEN CountPerChange ELSE #Deleted
END
FROM cte
INSERT INTO Logging.dbo.ETL_log (GenID, Startdate, Enddate, Process, Message, Inserts, Updates, Deleted,Description)
VALUES (#GenId, #start, GETDATE(), #Process, 'ETL succeded', #Inserts, #Updates, #Deleted,#Description)
if #OwnGenId = 1
UPDATE Logging.dbo.ETL_Gen
SET Endtime = GETDATE()
WHERE ID = #GenId
end try
begin catch
SET #ErrorNo = ERROR_NUMBER()
SET #ErrorMsg = ERROR_MESSAGE()
INSERT INTO Logging.dbo.ETL_Log (GenId, Startdate, Enddate, Process, Message, ErrorNo, Description)
VALUES (#GenId, #start, GETDATE(), #Process, #ErrorMsg, #ErrorNo,#Description)
end catch
GO

You invoke the function with 2 parameters (#GenId and #Description):
EXEC etl.etl_M_Update_Promo #GenID, #Description
However you have declared the function to take 1 argument:
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
SQL Server is telling you that [etl_M_Update_Promo] only takes 1 parameter (#GenId)
You can alter the procedure to take two parameters by specifying #Description.
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0,
#Description NVARCHAR(50)
AS
.... Rest of your code.

Use the following command before defining them:
cmd.Parameters.Clear()

This answer is based on the title and not the specific case in the original post.
I had an insert procedure that kept throwing this annoying error, and even though the error says, "procedure....has too many arguments specified," the fact is that the procedure did NOT have enough arguments.
The table had an incremental id column, and since it is incremental, I did not bother to add it as a variable/argument to the proc, but it turned out that it is needed, so I added it as #Id and viola like they say...it works.

For those who might have the same problem as me, I got this error when the DB I was using was actually master, and not the DB I should have been using.
Just put use [DBName] on the top of your script, or manually change the DB in use in the SQL Server Management Studio GUI.

Yet another cause of this error is when you are calling the stored procedure from code, and the parameter type in code does not match the type on the stored procedure.

I feel ashamed for even having to post this, but it might help someone in the future. Make sure you don't have a typo in your function call!
I kept getting this error trying to call a function and couldn't figure out why. My function and call had the same number of arguments (or so I thought).
Here's my function call:
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A,MIDDLENAME)
It's easier to see in Stack Overflow, but it wasn't so obvious in SSMS that I had a comma in place of a period for A.MIDDLENAME.
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A.MIDDLENAME)
Simple user error.

In addition to all the answers provided so far, another reason for causing this exception can happen when you are saving data from list to database using ADO.Net.
Many developers will mistakenly use for loop or foreach and leave the SqlCommand to execute outside the loop, to avoid that make sure that you have like this code sample for example:
public static void Save(List<myClass> listMyClass)
{
using (var Scope = new System.Transactions.TransactionScope())
{
if (listMyClass.Count > 0)
{
for (int i = 0; i < listMyClass.Count; i++)
{
SqlCommand cmd = new SqlCommand("dbo.SP_SaveChanges", myConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#ID", listMyClass[i].ID);
cmd.Parameters.AddWithValue("#FirstName", listMyClass[i].FirstName);
cmd.Parameters.AddWithValue("#LastName", listMyClass[i].LastName);
try
{
myConnection.Open();
cmd.ExecuteNonQuery();
}
catch (SqlException sqe)
{
throw new Exception(sqe.Message);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
myConnection.Close();
}
}
}
else
{
throw new Exception("List is empty");
}
Scope.Complete();
}
}

You either have to double check the Parameters on both side (StoredProcedure And Code):
Make Sure they are the same on both ends regarding to the number of them.
Make Sure you have NOT changed your StoredProcedure code and forgot to Execute it, nothing bad happens if you hit F5 to make sure have all the changes committed and saved.
Make Sure you you have the same naming convention on both sides (Not Likely to be the cause but it worth a shot).

Related

Return Bigint in a stored procedure

I have a stored procedure which has to return a bigint as output. below if the definition.
In the body, I'm inserting a row in a table and returning the identity using ##Identity in #LogID output variable.
Everything works except the return part. I have tried casting, converting, selecting and setting the #LogID to ##identity but no luck.
The stored proc is called by enterprise library's Logging block. I'm using Write method of Logwriter class. This is a standard class provided by Microsoft and we have not modified it. I can't show you the code which calls the procedure as this is a DLL and don't have the source code. Anyway, I'm pretty sure it's not the C# code as I get a SQLException so it is something in the sql. The code below is for brevity and there are lots of other columns which I have removed.They are all provided as input parameters.
I'm sure it's a stupid thing, but I'm somehow missing it.
CREATE PROCEDURE [dbo].[WriteLog]
(
#EventID int,
#Priority int,
#LogId bigint OUTPUT
)
INSERT INTO [Log] (EventID, Priority)
VALUES(#EventID,#Priority)
SET #LogID = ##identity
Go
Stored procedures can only return int. So you will need to use the output parameter.
declare #CapturedLogID bigint;
exec dbo.WriteLog #EventID = 42, #Priority = 1337, #LogID = #CapturedLogID output;
In the above example, after the procedure executes, #CapturedLogID stores the value set within the stored procedure (##identity, which, as others have pointed out, should be changed to scope_identity() immediately).
Edit: From C#, to call the procedure with an out parameter:
using (var cmd = new SqlCommand()) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "dbo.WriteLog";
cmd.Parameters.Add("EventID", SqlDbType.Int).Value = 42;
cmd.Parameters.Add("Priority", SqlDbType.Int).Value = 1337;
cmd.Parameters.Add("LogID", SqlDbType.BigInt).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
long logID = (long)cmd.Parameters["LogID"].Value;
}
Note that I've only included the code for setting up and executing the SqlCommand object.

How to deal with Stored Procedure?

Hello I am new in creating stored procedure can you help me how to do this.
Error:
Incorrect syntax near the keyword 'AS'.
Must declare scalar variable #Serial.
CREATE PROCEDURE sp_SIU
-- Add the parameters for the stored procedure here
#Serial varchar(50),
#Part varchar(50),
#Status varchar(50),
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
/*SET NOCOUNT ON;*/
-- Insert statements for procedure here
--where in my form if i enter serial number it will show select values
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
--Then if is correct it will Update Status on combobox
Update Table1 SET
Status=#Status
where SerialNumber=#SerialNumber
--then Insert Serial Number,Parnumber to Table 2
DECLARE #Count int
select #Count = Count(SerialNumber) from Table1 WHERE SerialNumber = #Serial
IF #Count = 0
BEGIN
INSERT INTO Table2 (SerialNumber,PArtNumber)
VALUES
(#Serial, #Part)
END
RETURN #Count
RETURN
Edit: Moved Updated info posted as an answer into Question
Oops my post is not that kind a miss.
It is possible to join this 3 sql string in one stored procedure?
Scenario:
{
What i have to do in my form is that i will enter serial number to txtserial.text by using the select sql it will show serialnumber,partnumber and status on lblserial.text,lblpartnumber.text and lblstatus.text.
And i will compare:
txtserial.text == lblserial.text
txtpartnumber.text == lblpartnumber.text
for my error handler.
{
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
}
Then if they are equal then:
I will update my Status from cbostatus.text if serial and part is correct then use sql upate.
{
Update Table1 SET
Status=#Status,
Modifiedby=#username,
DateModified=#Date
where SerialNumber=#Serial
}
Then insert serialnumber, using sql insert to another table.
{
INSERT INTO Table2 (SerialNumber,DateCreated,Createdby)
VALUES
(#Serial,#date,#username)
}
something likethis.
")
You have a rogue comma here
#Status varchar(50),
AS
and the name lurches between #Serial and #SerialNumber are these intended to be 2 different parameters?
Also what is the purpose of this line?
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
Currently it will just send back a 3 column result set to the calling application. Is that what it is intended to do (it doesn't seem to match the following comment which seems to imply it is meant to be some kind of check)?
Yes, you can execute 3 SQL statements inside one stored procedure. You probably want to declare some local variables inside your sproc to hold the intermediate results, i.e.
CREATE PROCEDURE BLAHBLAH
#SerialNumber VarChar(50)
AS
BEGIN
DECLARE #partnumber varchar(50);
SELECT #partnumber = partnumber FROM Table WHERE serialnumber = #SerialNumber;
...
SELECT #partnumber; --- return as recordset
RETURN #partnumber; --- return as return value
END
Then you can later insert #partnumber, test #partnumber, return #partnumber etc. I don't quite understand what you want to do; seems like you mostly want to look up a partnumber based on a serial number, but you want to do some uniqueness tests also. It would help if you could clarify the goal a bit more.
I recommend you ignore the user interface stuff for the moment. Write yourself some nice clean stored procedures that encapsulate the transaction and will do the right thing even if fired off at the same time from two different connections. Get everything working to your satisfaction in your SQL environment. Then go back to the user interface.
Oops my post is not that kind a miss.
It is possible to join this 3 sql string in one stored procedure?
Scenario:
What I have to do in my form is that I will enter serial number to txtserial.text by using the select sql it will show serialnumber,partnumber and status on lblserial.text,lblpartnumber.text and lblstatus.text.
AndI will compare:
txtserial.text == lblserial.text
txtpartnumber.text == lblpartnumber.text
for my error handler.
{
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
}
Then if they are equal then:
I will update my Status from cbostatus.text if serial and part is correct then use sql update.
{
Update Table1
SET Status = #Status,
Modifiedby = #username,
DateModified = #Date
where SerialNumber = #Serial
}
Then insert serialnumber, using sql insert to another table.
{
INSERT INTO Table2(SerialNumber, DateCreated, Createdby)
VALUES(#Serial, #date, #username)
}
something like this.

how to write a if else statement to insert query for showing the error in stored procedure

how to write a if else statement to insert query for showing the error in stored procedure
below is my stored procedure.I want to show a error message when already inserted student_id is insert again..Student_id is primary key so its show error in my code but i dono how to get that error and show ....how to do friends plz help me.....
ALTER PROCEDURE [dbo].[spinsertstudentapplication]
-- Add the parameters for the stored procedure here
#Student_id nvarchar(50),
#Select_Country nvarchar(50),
#Select_State nvarchar(50),
#Select_Franchise nvarchar(50),
#Select_Sensei nvarchar(50),
#Enter_Student_Name nvarchar(50),
#Enter_Student_Address nvarchar(50),
#Students_Father_Name nvarchar(50),
#Student_DOB datetime,
#Gender bit,
#Group nvarchar(50),
#Enter_Kyu nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into StudentApplication(Student_id,Select_Country,Select_State,Select_Franchise,Select_Sensei,Enter_Student_Name,Enter_Student_Address,Students_Father_Name,Student_DOB,Gender,[Group],Enter_Kyu)values(#Student_id,#Select_Country,#Select_State,#Select_Franchise,#Select_Sensei,#Enter_Student_Name,#Enter_Student_Address,#Students_Father_Name,#Student_DOB,#Gender,#Group,#Enter_Kyu)
END
You can add an output parameter(int/bit) in Sp and set value to that parameter whether record exist or not. Then you can check the output parameter value in Front End. Below I've added an output parameter #RecordExist as bit and setting the value 1 when record already exists otherwise setting 0. In front end you can get the Parameter value from SqlCommand after executing the Sp. (SqlCommand.Parameters["#RecordExist"].Value)
ALTER PROCEDURE [dbo].[spinsertstudentapplication]
-- Add the parameters for the stored procedure here
#Student_id nvarchar(50),
#Select_Country nvarchar(50),
#Select_State nvarchar(50),
#Select_Franchise nvarchar(50),
#Select_Sensei nvarchar(50),
#Enter_Student_Name nvarchar(50),
#Enter_Student_Address nvarchar(50),
#Students_Father_Name nvarchar(50),
#Student_DOB datetime,
#Gender bit,
#Group nvarchar(50),
#Enter_Kyu nvarchar(50),
#RecordExist bit output -- newly added parameter
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
If Exists (Select * from StudentApplication where Student_id = #Student_id)
Begin
Select #RecordExist = 1
return
End
Else
Begin
insert into StudentApplication (Student_id, Select_Country, Select_State, Select_Franchise, Select_Sensei, Enter_Student_Name, Enter_Student_Address, Students_Father_Name, Student_DOB, Gender, [Group], Enter_Kyu)
Select #Student_id, #Select_Country, #Select_State, #Select_Franchise, #Select_Sensei, #Enter_Student_Name, #Enter_Student_Address, #Students_Father_Name, #Student_DOB, #Gender, #Group, #Enter_Kyu
Select #RecordExist = 0
return
End
END
As Dean 'codeka' Harding mentioned in the comment, it would be helpful to know how you're calling the stored proc. But here are some general suggestions.
First, a common convention for stored procedures is to return 0 on success and non-zero value on error (you can use an output parameter for error codes, but it's kind of redundant).
Second, before attempting to insert a value, you should check if it already exists. E.g. here is some pseudo code:
if exists (select 1 from StudentApplication where Student_ID = #Student_ID)
begin
raiserror('Student ID already exists.', 16, 1)
return 1 -- Your caller would need to know that 1 identifies existing record
end
Notice that in this example, T-SQL code exits after calling raiserror, so you need to handle this as an exception if you call the stored proc from C#/VB.NET/etc. Alternatively, you can omit the raiserror call and just have the stored proc return an expected (by the client) error code.
Then there is still a minor possibility that a duplicate would be inserted, but I think that it would generate a fatal error that you would need to handle in the client code (error handling is dependent on the client; in C#, you will probably get a SqlException which you can query for specific code).
Another option would be to put a transaction around the code that checks for existing record and then inserts a new one.
If you want to handle error in C#, you need to take care of two things. First, check the return code and process non-zero values accordingly (the C# client and stored proc have to agree on the meaning of each error code). Then, you also need to handle SqlExceptions. The State and Number properties of the SqlException object can help you identify the problem. Keep in mind that for error messages defined on the fly (as in my example), Number will alway return 50,000 (I think).
You can add an output parameter at the top of your SP:
#ErrorOutput INT OUTPUT
Then add:
IF EXISTS (SELECT 1 FROM StudentApplication WHERE Student_id=#Student_id)
SET #ErrorOutput = -1;
RETURN #ErrorOutput;
ELSE
-- Insert statement

How to stop inserting records in SQL table when a limit is reached

I am using VB.net and SQL Server 2005.
My Problem is that I want to give user a message if the delegate limit has reached for that course.
See I have a course where I have MinDelegate and MaxDelegate limit. I want to stop inserting and give user message that "Max Delegate limit has reached can't have more delegates for this course"
And below is the insert commmand which is inserting records in my delegate table.
ALTER PROCEDURE [dbo].[uspInsertDelegate]
(
#CourseID int,
#CPUserID int,
#StatusID int,
#CreateUser varchar(25),
#CourseDate smalldatetime
)
AS
SET NOCOUNT OFF;
IF NOT EXISTS (SELECT *
FROM tblDelegate
WHERE CourseID = #CourseID and CPUserID = #CPUserID)
BEGIN
INSERT INTO tblDelegate
(
CourseID,
CPUserID,
StatusID,
CreateUser
)
VALUES
(
#CourseID,
#CPUserID,
#StatusID,
#CreateUser
)
END
UPDATE tblTraining
SET
TrainingDT = #CourseDate,
TrainingCompleted = #StatusID
WHERE CPUserID = #CPUserID
RETURN
Please also suggest what do in VB.NET code!
Thanks!
Best Regards,
Yuv
A solution is to write a "before INSERT" trigger which will enforce the business rules by checking how many students are readily registered for the class etc.) and prevent the insert to take place.
This error condition can then be detected at higher levels, and a proper error message provided to the user.
In re-reading your question, the business rule could as well be checked in the stored procedure you have in place, it would then just be a matter of making the store procedure return a condition code (say an integer: 0 = insert ok and -1 = class is full), and to test this value at the level of the application.
Edit: more details (but not quite the full code...)
Yuvraj, this looks seriously like homework, so I'd like to put you on the right track but also let you work at it enough that you learn the process of figuring things out.
With regards to the Store Procedure (SP), bniwredyc readily provided you the code:
It is a slight modification compared with what you have in your question:
#minDelegate int,
#maxDelegate int
set #delegatesCount = (select count(*) from tblDelegate
where CourseID = #CourseId)
if (#delegatesCount >= maxDelegate)
return -1
Essentially you add 2 extra arguments to the procedure: minDelegate and maxDelegate and return prematurely from the procedure, with a -1 return value, in case there are too many delegates. (1 in bniwredyc 's example, but I prefer negative values for error conditions). I don't think minDelegate is used at all; you know better which rules have to applied...
Now, you need to write a VB program which will invoke this SP by way of ADO. This will involve using the ADODB.Command object This Microsoft MSDN page provides reference info about this object and following a few links not too far from this page, you'll also find details about the Connection object and the RecordSet Object.
There are 3 ways that a stored procedure can return some data to the calling method.
1. By returning an integer value in the RETURN value. This value is
the return value of the Command object's Execute() method.
This is the simpler approach and can be used in your case
2. By returning values (integer, text or other) in one or several OUTPUT
Parameters
3. By returning a recordset
Method 2 can be combined with 1 or 3, however 1 and 3 are mutually
exclusive since they both use return value of the Execute() method
to provide an integer (1) or a Recordset (3).
The example at this page shows +/- all that you will need, but it uses a recordset for the data, which is not necessary in your case; Instead use an integer value for storing the return value of Execute(), and test it. If 0 : Record was added ok, If-1 : Failed the "too many" test.
Now, get to work :-) and please do tag your questions as "Homework" when appropriate.
You could create a validation stored procedure that just returns the total count of records. Call this first from your VB code then you check that count and then return the appropriate error message orelse call the insert sproc your provided.
You can pass a variable to the Stored Procedure with the MaxDelegates and do the check inside the Stored Procedure before inserting
Declare #CurrentNumberOfDelegates int
Select #CurrentNumberOfDelegates = Count(*)
From tblDelegate
Where CourseId = #CourseId
If #CurrentNumberOfDelegates > #MaxDelegates
Return -1
In this case you will check on VB.Net the return value of the stored procedure and if it is -1 show the message to the user.
This solution should be safe enough because you check the count just before you insert, but you may need to add a transaction to ensure that the limit is never passed by another thread running at the same time.
I think you can use this code for stored procedure:
ALTER PROCEDURE [dbo].[uspInsertDelegate]
(
#CourseID int,
#CPUserID int,
#StatusID int,
#CreateUser varchar(25),
#CourseDate smalldatetime,
#minDelegate int,
#maxDelegate int
)
AS
SET NOCOUNT OFF;
IF NOT EXISTS (SELECT *
FROM tblDelegate
WHERE CourseID = #CourseID and CPUserID = #CPUserID)
BEGIN
set #delegatesCount = (select count(*) from tblDelegate where CourseID = #CourseId)
if (#delegatesCount >= maxDelegate)
return 1
else
begin
INSERT INTO tblDelegate
(
CourseID,
CPUserID,
StatusID,
CreateUser
)
VALUES
(
#CourseID,
#CPUserID,
#StatusID,
#CreateUser
)
end
END
UPDATE tblTraining
SET
TrainingDT = #CourseDate,
TrainingCompleted = #StatusID
WHERE CPUserID = #CPUserID
RETURN 0
In VB code just check value that returned by execution of stored procedure: if it's 1 than max delegate limit has reached. You can also add some code to stored procedure to return value 2 in case of min limit have reached.
First of all thanks to all members who responded my Question
I solve this problem using below logic
In Sql Procedure I changed my procedure.
ALTER PROCEDURE [dbo].[uspInsertDelegate]
(
#CourseID int,
#CPUserID int,
#StatusID int,
#CreateUser varchar(25),
#CourseDate smalldatetime,
#MaxDelegate int
)
AS
SET NOCOUNT OFF;
IF NOT EXISTS (SELECT * FROM tblDelegate WHERE CourseID = #CourseID and CPUserID = #CPUserID)
BEGIN
Declare #DelegateBooked int
set #DelegateBooked = (SELECT count(*) FROM tblDelegate WHERE CourseID = #CourseID)
IF #DelegateBooked >= #MaxDelegate
SELECT 1
ELSE
BEGIN
INSERT INTO tblDelegate
(
CourseID,
CPUserID,
StatusID,
CreateUser
)
VALUES
(
#CourseID,
#CPUserID,
#StatusID,
#CreateUser
)
UPDATE tblTraining
SET
TrainingDT = #CourseDate,
TrainingCompleted = #StatusID
WHERE CPUserID = #CPUserID
END
END
And in my VB.net code I write:
Protected Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
If Not Session("CourseDate") Is Nothing Then
Try
Dim conString As String = WebConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString
Dim con As New SqlConnection(conString)
con.Open()
Dim cmd As SqlCommand
For Each curRow As GridViewRow In GridView1.Rows
Dim chkSelect As CheckBox = CType(curRow.Cells(1).FindControl("chkSelect"), CheckBox)
If chkSelect.Checked Then
cmd = New SqlCommand("uspInsertDelegate", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#CourseID", SqlDbType.Int).Value = Session("CourseID")
cmd.Parameters.Add("#CPUserID", SqlDbType.Int).Value = CType(curRow.Cells(1).FindControl("lblCPUserID"), Label).Text
cmd.Parameters.Add("#StatusID", SqlDbType.Int).Value = 25
cmd.Parameters.Add("#CreateUser", SqlDbType.VarChar).Value = Session("LoggedInUser")
cmd.Parameters.Add("#CourseDate", SqlDbType.DateTime).Value = Session("CourseDate")
cmd.Parameters.Add("#MaxDelegate", SqlDbType.Int).Value = Session("MaxDelegate")
Dim retValue As Integer = CType(cmd.ExecuteScalar(), Integer)
If retValue = 1 Then
lblError.Visible = True
lblError.Text = "Max Delegate limit has reached can't have more delegates for this course"
Exit For
Else
lblError.Visible = False
End If
End If
Next
GridView1.DataBind()
Catch ex As Exception
ErrorHandler.WriteError(ex.Message)
End Try
End If
Please have a look and provide your feedbacks in case it is wrong

SQL Error handling

Can you tell me if error handling is worth putting into this stored procedure?
-- **********************************************
-- Delete and create a new 'Truncate' function...
-- **********************************************
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = 'truncate_description' AND
type = 'FN')
DROP FUNCTION truncate_description
GO
CREATE FUNCTION truncate_description(#description varchar(1000), #numchars int=500) RETURNS varchar(500)
BEGIN
DECLARE #newDescription varchar(500);
DECLARE #truncMessage varchar(33);
SET #truncMessage = '..Click on title to read article.';
IF (len(#description) >= #numchars)
IF (substring(#description, #numchars, 1) = '.')
SET #newDescription = #description;
ELSE
BEGIN
SET #newDescription = substring(#description, 1, #numchars - len(#truncMessage));
IF (charindex('.', #newDescription) > 0)
BEGIN
WHILE (substring(#newDescription, len(#newDescription), 1) <> '.')
BEGIN
SET #newDescription = substring(#newDescription, 1, len(#newDescription) - 1);
END
END
SET #newDescription = #newDescription + #truncMessage;
END
ELSE
SET #newDescription = #description;
RETURN #newDescription;
END
GO
-- *********************************************
-- Delete and create a new 'Truncate' trigger...
-- *********************************************
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = 'tr_tblProfile_truncateDescription' AND
type = 'TR')
DROP TRIGGER tr_tblProfile_truncateDescription;
GO
CREATE TRIGGER tr_tblProfile_truncateDescription ON tbl_profile
AFTER INSERT, UPDATE AS
BEGIN
UPDATE tbl_profile
SET description = dbo.truncate_description(i.description, 500)
FROM tbl_profile p INNER JOIN inserted i on p.id=i.id
END
GO
-- ******************************************
-- Run the trigger on all existing records...
-- ******************************************
UPDATE tbl_Profile
SET description = description
GO
Many Thanks,
First of all - it's a function, not a stored procedure.
But error handling is always good - however a SQL function is probably not the best place to put it.
Considering this function works on a known schema and known data format (varchar) with known SQL functions (len, substring)... you should be able to unit-test this and consider any errors it may throw as extrinsic to the function itself.
It makes me lean towards an answer of no, don't handle errors here.
Implementing custom error handling within your T-SQL coding is a good if not essential practice in my opinion.
If the stored procedure/function that you are looking to develop is to form part of an applications middle tier, then I would recommend that you implement your own custom error handling.
By this I mean that you should raise errors that are specific to circumstances generated by your applications processes and log these in a generic error log table within the appropriate database.
An example of how to do this and incorporate it into the typical try catch block can be found within SQL Server Books Online.
Particularly the section titled: Error Handling Solution in the Adventure Works Database
http://msdn.microsoft.com/en-us/library/ms179296(SQL.90).aspx