Parameterized store procedures in VB.net - sql

I'm getting an error when the 'insertcommand' is executed telling me that I'm missing the parameters for the stored procedure. Do I need to put the parameter names in the Sql statement after the procedure as if I were calling it in SQL? I saw an example online that just added the parameters like I have here, but this doesn't work? I also put the sql state for the stored procedure below the 'AddRepair Sub'
Public Shared Sub AddRepair(ByVal repair As ClubRepair)
Dim conn As SqlConnection = ClubRentalsDB.getconnection
Dim insertcommand As New SqlCommand("AddRepair", conn)
insertcommand.Parameters.AddWithValue("#Name", repair.Name)
insertcommand.Parameters.AddWithValue("#ID", repair.MemberID)
insertcommand.Parameters.AddWithValue("#Phone", repair.PhoneNumber)
insertcommand.Parameters.AddWithValue("#Email", repair.Email)
insertcommand.Parameters.AddWithValue("#Work", repair.WorkToBeDone)
insertcommand.Parameters.AddWithValue("#Specification", repair.Specification)
insertcommand.Parameters.AddWithValue("#SoonestDate", repair.SoonestCompletion)
insertcommand.Parameters.AddWithValue("#PromisedDate", repair.DatePromised)
insertcommand.Parameters.AddWithValue("#ClubType", repair.TypeOfClub)
insertcommand.Parameters.AddWithValue("#GripType", repair.TypeOfGrip)
insertcommand.Parameters.AddWithValue("#NumOfClubs", repair.NumOfClubs)
insertcommand.Parameters.AddWithValue("#SpecialInstructions", repair.SpecialInstructions)
Try
conn.Open()
insertcommand.ExecuteReader()
Catch ex As Exception
MessageBox.Show(messageBad & ex.ToString)
Finally
conn.Close()
End Try
End Sub
USE [ClubRentals]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AddRepair] (#Name Varchar(50), #ID varchar(20),
#Phone varchar(50),#Email varchar(50), #Work varchar(20),#Specification varchar(MAX),
#SoonestDate date, #PromisedDate Date, #ClubType varchar(50), #Griptype varchar(50),
#NumOfClubs int, #SpecialInstructions varchar(MAX)) as
Insert into ClubRepair(Member_Name,Member_ID,Phone,Email,WorkToBeDone,Specification,
SoonestPossibleCompletion,DatePromised,TypeOfClub, TypeOfGrips ,NumOfClubs,
SpecialInstructions)
values(#Name, #ID, #Phone, #Email, #Work, #Specification,
#SoonestDate, #PromisedDate, #ClubType, #GripType,
#NumOfClubs,#SpecialInstructions)
GO

Confirm that every parameter value you are setting is not Nothing. Parameters with no value can cause the missing parameter error. There's a two-argument version of If() that helps:
insertcommand.Parameters.AddWithValue("#Specification", If(repair.Specification, ""))
this will return repair.Specification if it is not Nothing, and "" otherwise.
also, you should consider using Parameters.Add().Value() instead of .AddWithValue(), like so:
insertcommand.Parameters.Add("#ClubType", SqlDbType.VarChar, 50).Value = If(repair.TypeOfClub, "")
This is really useful when you're working with types other than string.

Try setting sqlcommand commandtype to storedprocedure.

make sure to respect case sensitivity, for an example
insertcommand.Parameters.AddWithValue("#GripType", repair.TypeOfGrip)
is wrong
insertcommand.Parameters.AddWithValue("#Griptype", repair.TypeOfGrip)
is right

Related

insert form data into database using stored procedure in classic asp

I have a form. Its data must be inserted into database (sql server 2008). I have written procedure to insert. How can i insert form data using stored procedure in classic ASP? Need some help as am new to asp and ado.
ALTER PROCEDURE INSERTVALUE
#COMPANY_ID INT ,
#COMPANY_NAME VARCHAR(20),
#SALES_REP VARCHAR (20),
#CONTRACT_ADMIN VARCHAR (20)
AS
BEGIN
INSERT INTO [form].[dbo].[COMPANY]
([COMPANY_ID]
,[COMPANY_NAME]
,[SALES_REP]
,[CONTRACT_ADMIN])
VALUES (#COMPANY_ID,#COMPANY_NAME,#SALES_REP,#CONTRACT_ADMIN);
END
GO
Edit (originally and wrongly posted as answer)
I tried to execute the following code but error occurs. ADODB.Command error '800a0bb9' Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another. /AddForm.asp, line 15 –
set rs=Server.CreateObject("ADODB.recordset")
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cnn
sql = " SELECT * FROM COMPANY"
rs.Open sql, cnn
If Request("submit") <> "" Then
cmd.CommandText = "INSERTVALUE"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("#COMPANY_ID",adint,adParamInput,10,Request.form("CompanyId"))
cmd.Parameters.Append cmd.CreateParameter("#COMPANY_NAME",advarchar,adParamInput,10, Request.form("company_name"))
cmd.Parameters.Append cmd.CreateParameter("#SALES_REP",advarchar,adParamInput,10,Request.form("sales_rep"))
cmd.Parameters.Append cmd.CreateParameter("#CONTRACT_ADMIN",advarchar,adParamInput,10, Request.form("contract_admin"))
cmd.Execute
End If
One possible cause of your problems and the tutorial don't tell you (or at least the ones I found didn't): if the adovbs.inc files is not found, it will give you:
ADODB.Comman error '800a0bb9'
Arguments are of the wrong type, are out of acceptable range, or are in conflict
with one another.
I had to explicitly include a copy of it.

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.

MS SQL get values after INSERT

I am facing an issue where I need to calculate some data based on existing data, then insert that data and finally, return it to an Excel file using VBA.
I have successfully been able to create a stored procedure that returns a table of values after inserting:
[...]
INSERT INTO [ExcelRGA] (RM_prefix, RM_suffix, editing, createdBy, editedBy) values (#RM_prefix, #RM_suffix, 1, #user, #user);
DECLARE #tab table (RM varchar(20))
INSERT #tab SELECT (#RM_prefix +'-' + right('00' + #RM_suffix, 3)) as 'RM';
SELECT * FROM #tab
END
and this works! However, I am unable to get the values it is returning using VBA
Set oRS = New ADODB.Recordset
Set cmd = New ADODB.Command
Dim objRec As Object
cmd.ActiveConnection = oCon
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "dbo.newRM"
cmd.Parameters.Refresh
cmd.Parameters("#user").Value = "john"
Set oRS = cmd.Execute()
but I try to do something like
while not oRS.eof
....
wend
get an error message stating that the recordset is closed and I cannot do my thing.
All I am trying to do is secure the information that I have computed (RM_prefix and RM_suffix), insert them into my table and return them to my Excel file.
If there is a way to do this without using a store procedure (such as a function) that would also be great!
Please keep in mind that this is a multi-user environment, so generating the values in Excel, sending them to the SQL server for an insert doesn't give a 100% guarantee regarding the uniqueness of said data.
Thank you all for your precious help and inputs!
Peter
You need something like this -
Private Function GetIDENTITY() As Long
oRS.Open "SELECT ##identity AS NewID", oCon
If Not IsNull(oRS.Fields("NewID")) Then
GetIDENTITY = oRS.Fields("NewID"): oRS.Close
Else
MsgBox "Error: Identity value not returned.", vbCritical
End
End If
End Function
Actually, the issue was coming from the SQL Stored Procedure. I've added
SET NOCOUNT ON;
right before the
INSERT INTO [ExcelRGA] (RM_prefix, RM_suffix, editing, createdBy, editedBy) values (#RM_prefix, #RM_suffix, 1, #user, #user);
And it has solved my problem! I can now browse the recordset in VBA.
Thank you all for your help and inputs!

Procedure or function !!! has too many arguments specified

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).

Updating Value in SQL Server using MS Access Using VB.Net Programming

I have a critical requirement , need to update a table in Sql server from access through forms and buttons,
When a user clicks the button in the form he should be able to update the record which is already existing in the database.
For Eg: table has columns -EmployeeID , Employee Name, Employee Location
EmployeeID Values
-----
1001|
2301|
3212|
Suppose a user wants to update value of EmployeeName alone not employee location ,he should be able to do that in some case employee.
update table set EmployeeName=#New_employee_name , Employee Location=#New_employee_location where EmployeeID=#Employee_ID
This should be driven through vb. net program inorder to update the user input value in the database.
I would recommend you create a Stored Procedure on the SQL Server, here is an example:
CREATE PROCEDURE sp_UpdateEmployeeByID
(
#ID int,
#TitleID int,
#FirstName nvarchar(255),
#LastName nvarchar(255)
)
AS
BEGIN
SET NOCOUNT ON;
UPDATE Employee SET
TitleID = #TitleID,
FirstName = #FirstName,
LastName = #LastName
WHERE ID = #ID
END
Using stored procedures rather than ad-hoc SQL protects you from SQL Injection attacks plus there are performance benefits.
Then using VB.Net you will want to call the Stored Procedure, passing in the updated employee values.
Public Sub UpdateEmployeeByID(Byval ID As Int32, Byval TitleID As Int32, Byval FirstName As string, Byval LastName As string)
Dim connString As String = ConfigurationManager.AppSettings("ConnectionString")
Dim conn As New SqlConnection(connString)
conn.Open()
Dim sqlCommand As new SqlClient.SqlCommand("sp_UpdateEmployeeByID", conn)
sqlCommand.CommandType = CommandType.StoredProcedure
sqlCommand.Parameters.AddWithValue("#ID", ID)
sqlCommand.Parameters.AddWithValue("#TitleID", TitleID)
sqlCommand.Parameters.AddWithValue("#FirstName", FirstName)
sqlCommand.Parameters.AddWithValue("#LastName", LastName)
Try
sqlCommand.ExecuteNonQuery()
Catch ex As SqlException
'Handle SQL exceptions
Catch ex As Exception
'Handle exceptions
Finally
'clean up resources that access Data
If IsNothing(sqlCommand) = False Then
sqlCommand.Dispose()
sqlCommand = Nothing
End If
conn.Close()
End Try
End Sub