Insert and Select at the same time in a stored procedure - sql

I have the following stored procedure:
create procedure Insert_Maintenance
(
#PlateNo nvarchar(10),
#MaintenanceType nvarchar(150),
#Name nvarchar(300),
#MaintenanceDate date,
#Qty int,
#IndivisualVal float,
#TotalVal float,
#Notes nvarchar(300)
)
as
insert into Maintenance(MaintenanceNo, PlateNo, MaintenanceType, AutoCenterNo,MaintenanceDate, Qty, IndivisualVal, TotalVal, Notes)
values ((1+(select Max(MaintenanceNo) from Maintenance)), #PlateNo, #MaintenanceType, (select AutoCenterNo from AutoCenter where Name = #Name), #MaintenanceDate, #Qty, #IndivisualVal, #TotalVal, #Notes)
Select Max(MaintenanceNo) AS MNo from Maintenance
A user will insert new maintenance operation via VB.NET interface. The information of the maintenance will be inserted into the database. The ID of the maintenance will increase by 1; as it is shown in the code. Since this is the case, after inserting the information I want to show a message that tells the user that information entered correctly and the ID of this operation is the value of MNo.
Basically, the problem is not with the VB.NET code because the message works fine but the problem is related to the select statement that shows the maintenance ID to the user.
The code in VB.NET
Dim ConnectString As String
ConnectString = ""
Dim connection As New SqlConnection(ConnectString)
'Dim parm1 As SqlParameter
'parm1 = New SqlParameter("#MaintenanceNo", SqlDbType.Int)
'parm1.Value = MaintenanceNoTextBox.Text
Dim parm2 As SqlParameter
parm2 = New SqlParameter("#PlateNo", SqlDbType.NVarChar)
parm2.Value = PlateNoComboBox.Text
Dim parm3 As SqlParameter
parm3 = New SqlParameter("#MaintenanceType", SqlDbType.NVarChar)
parm3.Value = MaintenanceTypeTextBox.Text
Dim parm4 As SqlParameter
parm4 = New SqlParameter("#Name", SqlDbType.NVarChar)
parm4.Value = NameComboBox.Text
Dim parm5 As SqlParameter
parm5 = New SqlParameter("#MaintenanceDate", SqlDbType.Date)
parm5.Value = MaintenanceDateDateTimePicker.Value
Dim parm6 As SqlParameter
parm6 = New SqlParameter("#Qty", SqlDbType.Int)
parm6.Value = QtyTextBox.Text
Dim parm7 As SqlParameter
parm7 = New SqlParameter("#IndivisualVal", SqlDbType.Float)
parm7.Value = IndivisualValTextBox.Text
Dim parm8 As SqlParameter
parm8 = New SqlParameter("#TotalVal", SqlDbType.Float)
parm8.Value = TotalValTextBox.Text
Dim parm9 As SqlParameter
parm9 = New SqlParameter("#Notes", SqlDbType.NVarChar)
parm9.Value = NotesTextBox.Text
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = connection
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "Insert_Maintenance"
'cmd.Parameters.Add(parm1)
cmd.Parameters.Add(parm2)
cmd.Parameters.Add(parm3)
cmd.Parameters.Add(parm4)
cmd.Parameters.Add(parm5)
cmd.Parameters.Add(parm6)
cmd.Parameters.Add(parm7)
cmd.Parameters.Add(parm8)
cmd.Parameters.Add(parm9)
Try
connection.Open()
cmd.ExecuteNonQuery()
Dim dreader As SqlDataReader
dreader = cmd.ExecuteReader()
Dim a As String
a = dreader("MNo").ToString
MessageBox.Show("Information entered, ID is " + a)
dreader.Close()
'MaintenanceNoTextBox.Text = ""
PlateNoComboBox.Text = ""
MaintenanceTypeTextBox.Text = ""
NameComboBox.Text = ""
'MaintenanceDateDateTimePicker.Value = ""
QtyTextBox.Text = ""
IndivisualValTextBox.Text = ""
TotalValTextBox.Text = ""
NotesTextBox.Text = ""
Catch ex As Exception
MessageBox.Show("Something wrong (" + ex.Message + ")")
Finally
connection.Close()
End Try
Any suggestions guys !! Thanks

To solve your problem you need to just change one line and remove a bunch of unnecessary code
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = connection cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "Insert_Maintenance"
.... you need to build the parameters collection here .....
Try
connection.Open()
Dim result = cmd.ExecuteScalar() ' <- Instead of ExecuteNonQuery '
if result IsNot Nothing Then
Console.WriteLine("The Mno is:" & Convert.ToInt32(result)
End If
ExecuteScalar returns the first column of the first row in your results. This should resolve the VB.NET side of your code. Of course, if you don't need to control the values inserted in the column MaintenanceNo then the next action to take is to set the Identity property to Yes in the field properties. In this way you could remove the last lines of your storedprocedure and forget to pass anything for the MaintenaceNo field
INSERT INTO Maintenance(PlateNo, MaintenanceType, AutoCenterNo,MaintenanceDate, Qty,
IndivisualVal, TotalVal, Notes)
VALUES (#PlateNo, #MaintenanceType,
(select AutoCenterNo from AutoCenter where Name = #Name),
#MaintenanceDate, #Qty, #IndivisualVal, #TotalVal, #Notes)
SELECT SCOPE_IDENTITY()

I think ID of Maintainance table should be auto-increment. For achieving that you can set Is Identity to Yes
In the end of insert if you want the ID than you can get by
Select SCOPE_IDENTITY()
If you want to increment ID manually then try this :
declare #newid int
Select #newid = Max(ISNULL(MaintenanceNo, 0)) from Maintenance
set #newid = #newid + 1
then use #newid for insert and in the end Select #newid

Related

System.IndexOutOfRangeException: while inserting data to mdf database file

Im getting this error while inserting data to my mdf database file
System.IndexOutOfRangeException: 'An SqlParameter with ParameterName '#qtysold' is not contained by this SqlParameterCollection.'
This is my code for order function
Function order(ByVal cart As List(Of Integer), ByVal product_qty As List(Of Integer))
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
'INSERT INTO PRODUCT TABLE
cmd.CommandType = CommandType.Text
cmd.CommandText = "UPDATE product SET product_qty= product_qty - #qty WHERE product_id= #id"
cmd.Parameters.Add("#qty", SqlDbType.Int)
cmd.Parameters.Add("#id", SqlDbType.Int)
For i As Integer = 0 To cart.Count - 1
cmd.Parameters("#id").Value = cart(i)
cmd.Parameters("#qty").Value = product_qty(i)
cmd.ExecuteNonQuery()
Next
'INSERT INTO SALES TABLE
cmd.CommandType = CommandType.Text
cmd.CommandText = "INSERT INTO sales VALUES (#id, #productname, #qtysold, #date)"
cmd.Parameters.Add("#id", SqlDbType.Int)
cmd.Parameters.Add("#productname", SqlDbType.VarChar)
cmd.Parameters.Add("#qtysold", SqlDbType.Int)
cmd.Parameters.Add("#date", SqlDbType.Date)
For i As Integer = 0 To cart.Count - 1
cmd.Parameters("#id").Value = cart(i)
cmd.Parameters("#productname").Value = getName(cart(i))
cmd.Parameters("#qtysold").Value = product_qty(i)
cmd.Parameters("#date").Value = datefield.Text
cmd.ExecuteNonQuery()
Next
cart.Clear()
product_qty.Clear()
refresh()
End Function
THE ERROR HAPPENS HERE
cmd.Parameters("#qtysold").Value = product_qty(i)
That seems an odd exception in that situation as the code looks OK to me but it's wrong even if it did work. Don't add the parameters and then get them back by name over and over. The Add method you're calling returns the SqlParameter object added so assign it to a variable and then use that:
Dim idParameter = cmd.Parameters.Add("#id", SqlDbType.Int)
Dim productionNameParameter = cmd.Parameters.Add("#productname", SqlDbType.VarChar)
Dim qtySoldParameter = cmd.Parameters.Add("#qtysold", SqlDbType.Int)
Dim dateParameter = cmd.Parameters.Add("#date", SqlDbType.Date)
For i As Integer = 0 To cart.Count - 1
idParameter.Value = cart(i)
productionNameParameter.Value = getName(cart(i))
qtySoldParameter.Value = product_qty(i)
dateParameter.Value = datefield.Text
cmd.ExecuteNonQuery()
Next
NEVER use the same complex expression over and over. ALWAYS use it once and assign the result to a variable, then use that variable over and over. In this case, you don't even have to use the complex expression once, because you already had the object but just ignored it.

How to execute query and store data of a column in a variable in VB.net?

I have the following code where I am trying to execute a query and store the value from the database in two variables. Depending on the variables, I would like to tick a checkbox and add some text to a textbox.
Here is the code:
Try
Dim cn As SqlConnection
Dim strCnn As String = ConfigurationManager.ConnectionStrings("agilityconnectionstring").ConnectionString
cn = New SqlConnection(strCnn)
cn.Open()
Dim comm As New SqlCommand("select IsCompleted, CompletionDate from managerchecklist where ID = 53 and QuestionID = 1", cn)
comm.CommandType = CommandType.Text
Dim ds As SqlDataReader
ds = comm.ExecuteReader()
If ds.HasRows Then
While ds.Read
IsComplete = ds.Item("IsCompleted").ToString()
CompleteDate = ds.Item("CompletionDate").ToString()
identifytasks_done.Checked = True
identifytasks_date.Attributes.Add("style", "display:block")
identifytasks_date.Text = CompleteDate
End While
End If
''Close your connections and commands.
cn.Close()
Catch ex As Exception
''Handle error if any
End Try
But I seem to be going wrong somewhere. Can anyone please help me?
Depending on the variables, I would like to tick a checkbox and add some text to a textbox.
Have an If Statement to check the variables whether it is complete
If IsComplete = "complete" Then
identifytasks_done.Checked = True
identifytasks_date.Attributes.Add("style", "display:block")
identifytasks_date.Text = CompleteDate
End If
Move the checking to SQL statement
Dim comm As New SqlCommand(
"select IsCompleted, CompletionDate from " +
"managerchecklist where ID = 53 and QuestionID = 1 and "
"IsCompleted = 'complete'",
cn)
Consider using parameter SQL instead to prevent SQL injection
I would recommend a Using statement for SQL queries and also parameters.
Get the values from SQL then use an IF statement to do whatever based on the values.
Assuming IsCompleted is a bit field in SQL....
Dim isCompleted As Boolean
Dim completedDate As Date
Using con As New SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("agilityconnectionstring").ConnectionString)
Using cmd As New SqlClient.SqlCommand("SELECT [IsCompleted], [CompletionDate] FROM managerchecklist where [ID] = #managerchecklistID and [QuestionID] = #questionID", con)
cmd.Parameters.Add("#managerchecklistID", SqlDbType.Int).Value = 53
cmd.Parameters.Add("#questionID", SqlDbType.Int).Value = 1
con.Open()
Using reader As SqlClient.SqlDataReader = cmd.ExecuteReader
While reader.Read
'Index in order of the columns in the SELECT statement
If reader.GetSqlBoolean(0).IsNull = False Then isCompleted = reader.GetSqlBoolean(0)
If reader.GetSqlDateTime(1).IsNull = False Then completedDate = reader.GetSqlDateTime(1)
End While
End Using
End Using
End Using
If isCompleted Then
identifytasks_done.Checked = True
identifytasks_date.Attributes.Add("style", "display:block")
identifytasks_date.Text = completedDate
End If
You could place this in a Sub of it's own with managerchecklistID and questionID as arguments then set the parameter values with the arguments
cmd.Parameters.Add("#managerchecklistID", SqlDbType.Int).Value = managerchecklistID
cmd.Parameters.Add("#questionID", SqlDbType.Int).Value = questionID

Must declare the scalar variable "#Modifier"

I have been trying to figure out what I am doing wrong for a few hours now. I am trying to add a record to my database but I am not able to do so because of the error I am getting that reads "Must declare the scalar variable "#Modifier"." I noticed other people with similar issues but I couldn't apply the same fixes to my code.
Dim dbConnection As SqlConnection = connectToDb()
Dim sqlString As String
If currentWeapon.Id > 0 Then
sqlString = "Update Weapons Set Name = #name"
Else
sqlString = "INSERT INTO Weapons (Name, APPower, HEPower, Range, Modifier) VALUES(#name, #APPower, #HEPower, #Range, #Modifier)"
lastWeaponId += 1
currentWeapon.Id = lastWeaponId
End If
Dim com As New SqlCommand(sqlString, dbConnection)
com.Parameters.Add("#name", SqlDbType.VarChar).Value = currentWeapon.Name
com.Parameters.Add("#APPower", SqlDbType.Int).Value = currentWeapon.APPower
com.Parameters.Add("#HEPower", SqlDbType.Int).Value = currentWeapon.HEPower
com.Parameters.Add("#Range", SqlDbType.Int).Value = currentWeapon.Range
com.Parameters.Add("#Modifer", SqlDbType.VarChar).Value = currentWeapon.Modifier
Try
Dim result = com.ExecuteNonQuery()
MessageBox.Show(result.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
You wrote #Modifer instead of #Modifier
com.Parameters.Add("#Modifer", SqlDbType.VarChar).Value = currentWeapon.Modifier
^
You have a typo: #Modifer vs. #Modifier.
In your query, you use #Modifier:
"INSERT INTO Weapons (Name, APPower, HEPower, Range, Modifier)
VALUES(#name, #APPower, #HEPower, #Range, #Modifier)"
But you specify the parameter name on the command as #Modifer:
com.Parameters.Add("#Modifer", SqlDbType.VarChar).Value = currentWeapon.Modifier

Stored procedure and VB.net code not working : Too many arguments

I have the following stored procedure:
ALTER PROCEDURE p_InsertNewBatch
(
#customer_id VARCHAR(50),
#batch_number INT,
#batch_reference VARCHAR(50),
#output_location VARCHAR(150),
#create_date VARCHAR(50),
#batchid INT OUTPUT
)
AS
BEGIN
SET NOCOUNT ON;
declare #date datetime
set #create_date= convert(VARCHAR, #create_date, 1) -- as dd/mm/yyyy
INSERT INTO tbl_batches
(
[customer_id],
[batch_number],
[batch_reference],
[batch_output_location],
[create_date]
)
VALUES
(
#customer_id,
#batch_number,
#batch_reference,
#output_location,
#create_date
)
SELECT #batchid = SCOPE_IDENTITY();
END
And I run this stored procedure form a form OnCLick event:
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Dim intRowsAffected As Integer
'Try
Dim returnbatch As Integer = 0
Dim customerID As String
Dim batchref As String
Dim todaysdate As String = String.Format("{0:dd/MM/yyyy}", DateTime.Now)
Dim batchid As Integer
Dim myClientFolder As String
Dim myBatchFolder As String
con.ConnectionString = My.Settings.TestValue()
con.Open()
cmd.Connection = con
cmd.CommandText = "p_GetNextBatchNumber"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#CustomerID", SqlDbType.Char)
cmd.Parameters("#CustomerID").Value = txtCustomerNumber.Text
cmd.Parameters.Add("#NextBatch", SqlDbType.Int).Direction = ParameterDirection.Output
cmd.ExecuteNonQuery()
con.Close()
returnbatch = Convert.ToInt32(cmd.Parameters("#NextBatch").Value)
batchref = txtCustomerNumber.Text & "-" & returnbatch
txtBatchNumber.Text = returnbatch
txtBatchReference.Text = batchref
txtCreateDate.Text = todaysdate
customerID = txtCustomerNumber.Text
myClientFolder = "c:\Scanned Batches1\" & txtCustomerNumber.Text
myBatchFolder = "c:\Scanned Batches1\" & txtCustomerNumber.Text & "\" & txtBatchReference.Text
If Directory.Exists(myClientFolder) Then
Else
MsgBox("A new folder for this client will be created")
Directory.CreateDirectory(myClientFolder)
End If
' Now check that the Batch ID folder exists
If Directory.Exists(myBatchFolder) Then
MsgBox("A batch folder already exists with this name. Are you sure you want to continue", vbInformation)
Else
MsgBox("A new folder for this batch will be created", vbInformation)
Directory.CreateDirectory(myBatchFolder)
End If
txtOutputLoc.Text = "c:\Scanned Batches1\" & txtCustomerNumber.Text & "\" & txtBatchReference.Text
txtOutputLoc.Enabled = False
'INSERT into tbl_Batches the Batch Details
' #customer_id VARCHAR(50),
' #batch_number INT,
' #batch_reference VARCHAR(50),
' #output_location VARCHAR(150),
' #create_date datetime
con.Open()
cmd.CommandText = "p_InsertNewBatch"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#customer_id", SqlDbType.Char).Value = customerID
cmd.Parameters.Add("#batch_number", SqlDbType.Int).Value = returnbatch
cmd.Parameters.Add("#batch_reference", SqlDbType.Char).Value = batchref
cmd.Parameters.Add("#output_location", SqlDbType.Char).Value = txtOutputLoc.Text
cmd.Parameters.Add("#create_date", SqlDbType.Char).Value = todaysdate
cmd.Parameters.Add("#batchid", SqlDbType.Int).Direction = ParameterDirection.Output
cmd.ExecuteNonQuery()
intRowsAffected = cmd.ExecuteNonQuery()
con.Close()
batchid = Convert.ToInt32(cmd.Parameters("#batchid").Value)
txtID.Text = batchid
'Catch ex As Exception
'MessageBox.Show("Error while trying to add new batch..." & ex.Message, "Create Batch")
' Finally
con.Close()
'End Try
End Sub
However I keep getting an error :
System.Data.SqlClient.SqlException was unhandled
Procedure or function p_InsertNewBatch has too many arguments specified.
What's going on here? I've been looking over the code for ages and can't seem to see whats causing it.
Thanks
You're using a single command object to execute multiple SQL statements but you don't clear the parameters from the first one before adding new parameters for the second one. I would tend to create a new command object for each SQL statement but, if you're going to use the same one and change the CommandText then make sure that you clear the parameters too.

How to get last auto increment value in a table? VB.NET

How would you get the last Primary Key/Auto Increment value in a table using OleDb?
I need to get this value so I can create a folder for a record before it is added so that files can be copied to the folder when it is added.
Any idea?
I have tried as following.
##Identity 'Need to insert a record first and I can't do that without copying the files first
SELECT SCOPE_IDENTITY() 'Doesn't work with OleDb
This is the error message I get:
I think this might work:
SELECT MAX(ID) FROM MyTable
you can do it like this because of The Jet 4.0 provider supports ##Identity,
Reference
Dim query As String = "Insert Into Categories (CategoryName) Values (?)"
Dim query2 As String = "Select ##Identity"
Dim ID As Integer
Dim connect As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb"
Using conn As New OleDbConnection(connect)
Using cmd As New OleDbCommand(query, conn)
cmd.Parameters.AddWithValue("", Category.Text)
conn.Open()
cmd.ExecuteNonQuery()
cmd.CommandText = query2
ID = cmd.ExecuteScalar()
End Using
End Using
Try this
Select IDENT_CURRENT('TableName')
It Will retrun Last ID(If it's Auto increment) of your Table
reference
**c#**
string query = "Insert Into Categories (CategoryName) Values (?)";
string query2 = "Select ##Identity";
int ID;
string connect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb";
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.AddWithValue("", Category.Text);
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = query2;
ID = (int)cmd.ExecuteScalar();
}
}
**VB**
Dim query As String = "Insert Into Categories (CategoryName) Values (?)"
Dim query2 As String = "Select ##Identity"
Dim ID As Integer
Dim connect As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb"
Using conn As New OleDbConnection(connect)
Using cmd As New OleDbCommand(query, conn)
cmd.Parameters.AddWithValue("", Category.Text)
conn.Open()
cmd.ExecuteNonQuery()
cmd.CommandText = query2
ID = cmd.ExecuteScalar()
End Using
End Using
refer
You can try Check if NULL first :
Select if(IsNull(Max(ColName)),1,Max(ColName) + 1 ) From YourTable
try this (vb.net)
'''
Dim lastrecord As Integer
Dim command As New SqlCommand("Select IDENT_CURRENT('tbluom')+1", conn)
command.ExecuteNonQuery()
Dim dt As New DataTable()
Dim da As New SqlDataAdapter(command)
lastrecord = command.ExecuteScalar()
txt_uomid.Text = lastrecord
MsgBox(lastrecord)
Dim encode As String = txt_uomid.Text '"99999"
Dim encint As Integer = Integer.Parse(encode) '+ 1
encode = "00" & "-" & encint.ToString("00000").Substring(1, 4)
MsgBox(encode)
''''