Why do I get a "data type conversion error" with ExecuteNonQuery()? - sql

Why do I get an error converting varchar into float conversion when I run this code?
I can't figure it out, please help.
Imports System.Data.SqlClient
Public Class Form1
Dim selected As Double
Dim HourItem As Double
Dim OverTimeRate As Double
Dim connection As New SqlConnection("Data Source=DESKTOP-F55AVQ6\SQLEXPRESS;Initial Catalog=Db_Suncrest_Financial;Integrated Security=True")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'Db_Suncrest_FinancialDataSet.Tb_Suncrest_Financial_Payroll' table. You can move, or remove it, as needed.
Me.Tb_Suncrest_Financial_PayrollTableAdapter.Fill(Me.Db_Suncrest_FinancialDataSet.Tb_Suncrest_Financial_Payroll)
End Sub
Private Sub Employee_PositionComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Employee_PositionComboBox.SelectedIndexChanged
Select Case Employee_PositionComboBox.SelectedItem
Case "Banker"
selected = 14.75
Case "Bank Teller"
selected = 10
Case "Loan Processor"
selected = 17.1
Case "Mortgage Consultant"
selected = 19.22
Case "Investment Representative"
selected = 19.31
Case "Credit Analyst"
selected = 19.88
Case "Investment Banker"
selected = 22.75
Case "Relationship Manager"
selected = 23.85
Case "Financial Adviser"
selected = 23.99
Case "Financial Analyst"
selected = 25.84
Case "Asset Manager"
selected = 26.86
Case "Under Writer"
selected = 27.56
Case "Internal Auditor"
selected = 28.79
Case "Investment Banking Analyst"
selected = 39.37
Case "Loan Officer"
selected = 43.18
End Select
Rate_Per_HourTextBox.Text = selected
End Sub
Private Sub Hours_WorkedComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Hours_WorkedComboBox.SelectedIndexChanged
Select Case Hours_WorkedComboBox.SelectedItem
Case "8"
HourItem = 8
Case "7"
HourItem = 7
Case "6"
HourItem = 6
Case "5"
HourItem = 5
Case "4"
HourItem = 4
End Select
End Sub
Private Sub OverTime_RateComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles OverTime_RateComboBox.SelectedIndexChanged
Select Case OverTime_RateComboBox.SelectedItem
Case "Normal Day"
OverTimeRate = 1.25
Case "Rest Day"
OverTimeRate = 1.69
Case "Special Non-Working Hoiday"
OverTimeRate = 1.69
Case "Special Non-Working Hoiday + Rest Day"
OverTimeRate = 1.95
Case "Regular Holliday"
OverTimeRate = 2.6
Case "Regular Holliday + Rest Day"
OverTimeRate = 3.38
End Select
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Basic_PayTextBox.Text = HourItem * selected * 30
OverTime_PayTextBox.Text = OverTimeRate * selected * OverTime_HoursTextBox.Text
Gross_SalaryTextBox.Text = OverTime_PayTextBox.Text + Basic_PayTextBox.Text
Total_Salary_W_TaxTextBox.Text = Gross_SalaryTextBox.Text * (0.0034 + 0.0363 + 0.01375)
Date_TimeTextBox.Text = Format(Now, "General Date")
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
connection.Open()
Dim command As New SqlCommand("Insert into Tb_Suncrest_Financial_Payroll(Employee_Id_No, Employee_Name, Employee_Position, Residence, Date_Time, Hours_Worked, Rate_Per_Hour,
Basic_Pay, OverTime_Hours, OverTime_Rate, OverTime_Pay, Gross_Salary, SSS, Pagibig, Philhealth, Total_Salary_W_Tax)
Values(
'" & Employee_Id_NoTextBox.Text & "', '" & Employee_NameTextBox.Text & "', '" & Employee_PositionComboBox.Text & "', '" & ResidenceTextBox.Text & "', '" & Date_TimeTextBox.Text & "',
'" & Hours_WorkedComboBox.Text & "', '" & Rate_Per_HourTextBox.Text & "', '" & Basic_PayTextBox.Text & "', '" & OverTime_HoursTextBox.Text & "', '" & OverTime_RateComboBox.Text & "',
'" & OverTime_PayTextBox.Text & "', '" & Gross_SalaryTextBox.Text & "', '" & SSSTextBox.Text & "', '" & PagibigTextBox.Text & "', '" & PhilhealthTextBox.Text & "', '" & Total_Salary_W_TaxTextBox.Text & "')", connection)
command.Parameters.AddWithValue("#Employee_Id_No", SqlDbType.Int)
command.Parameters.AddWithValue("#Employee_Name", SqlDbType.VarChar)
command.Parameters.AddWithValue("#Employee_Position", SqlDbType.VarChar)
command.Parameters.AddWithValue("#Residence", SqlDbType.VarChar)
command.Parameters.AddWithValue("#Date_Time", SqlDbType.DateTime)
command.Parameters.AddWithValue("#Hours_Worked", SqlDbType.Int)
command.Parameters.AddWithValue("#Rate_Per_Hour", SqlDbType.Float)
command.Parameters.AddWithValue("#Basic_Pay", SqlDbType.Float)
command.Parameters.AddWithValue("#OverTime_Hours", SqlDbType.Float)
command.Parameters.AddWithValue("#OverTime_Rate", SqlDbType.Float)
command.Parameters.AddWithValue("#OverTime_Pay", SqlDbType.Float)
command.Parameters.AddWithValue("#Gross_Salary", SqlDbType.Float)
command.Parameters.AddWithValue("#SSS", SqlDbType.Float)
command.Parameters.AddWithValue("#Pagibig", SqlDbType.Float)
command.Parameters.AddWithValue("#Philhealth", SqlDbType.Float)
command.Parameters.AddWithValue("#Total_Salary_W_Tax", SqlDbType.Float)
If command.ExecuteNonQuery() = 1 Then
MessageBox.Show("Added")
Else
MessageBox.Show("Not Added")
End If
connection.Close()
End Sub
End Class

TL;DR; See this answer as to how to call SQL Server correctly.
Well, instead of using SQL parameters properly, you have just concatenated the values directly into the query. For example, although you have added a parameter:
command.Parameters.AddWithValue("#Employee_Id_No", SqlDbType.Int)
you are not actually using it:
'" & Employee_Id_NoTextBox.Text & "'
Instead you need to write your insert like this, no concatenation needed:
Values(#Employee_Id_No, #Employee_Name ...
See also this article by Dan Guzman about why not to use AddWithValue, especially for varchar columns.
You should use
Add("#Employee_Name", SqlDbType.VarChar, insert_column_length).Value = Employee_Id_NoTextBox.Text;
You should also not cache connection and command objects. Dispose them with using blocks.
EDIT
You also need to cast your Text values to the various types, for example CInt(Employee_Id_NoTextBox.Text)

Here is an example of the ideas presented by #Charlieface excellent answer.
A few points in addition.
It is very common for ID fields to be identity fields (auto-number) Check your database.
If this is the case then you would not include Employee_ID in the fields list, Values list of add anything to the parameters collection for that field. In your case this appears to be a payroll table so perhaps Employee_ID is a foreign key to an employees table elsewhere. In this case, the code is fine.
Users are apt to enter anything is a TextBox. I strongly suggest that you validate all the input for numbers and dates with .TryParse before attempting the insert.
Never present a message box while a connection is open. Connections are precious resources and should be opened directly before the .Execute... and closed as soon as possible with End Using.
There appears to be several calculated fields that do not need to be stored at all but storage is cheap and it will probably make other queries simpler.
Private ConStr As String = "Your connection string"
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim RetVal As Integer
Dim Sql = "Insert into Tb_Suncrest_Financial_Payroll(Employee_Id_No, Employee_Name, Employee_Position, Residence, Date_Time, Hours_Worked, Rate_Per_Hour,
Basic_Pay, OverTime_Hours, OverTime_Rate, OverTime_Pay, Gross_Salary, SSS,
Pagibig, Philhealth, Total_Salary_W_Tax)
Values(
#Employee_Id_No, #Employee_Name, #Employee_Position, #Residence, #Hours_Worked,#Rate_Per_Hour,
#Basic_PayTextBox, #OverTime_Hours, #OverTime_Rate, #Gross_Salary, #SSS,
#Pagibig, #Philhealth, #Total_Salary_W_Tax);"
Using connection As New SqlConnection(ConStr),
command As New SqlCommand(Sql, connection)
With command.Parameters
.Add("#Employee_Id_No", SqlDbType.Int).Value = CInt(Employee_Id_NoTextBox.Text)
.Add("#Employee_Name", SqlDbType.VarChar).Value = Employee_NameTextBox.Text
.Add("#Employee_Position", SqlDbType.VarChar).Value = Employee_Position.Text
.Add("#Residence", SqlDbType.VarChar).Value = ResidenceTextBox.Text
.Add("#Date_Time", SqlDbType.DateTime).Value = CDate(Date_TimeTextBox.Text)
.Add("#Hours_Worked", SqlDbType.Int).Value = CInt(Hours_WorkedComboBox.Text)
.Add("#Rate_Per_Hour", SqlDbType.Float).Value = CDbl(Rate_Per_HourTextBox.Text)
.Add("#Basic_Pay", SqlDbType.Float).Value = CDbl(Basic_PayTextBox.Text)
.Add("#OverTime_Hours", SqlDbType.Float).Value = CDbl(OverTime_HoursTextBox.Text)
.Add("#OverTime_Rate", SqlDbType.Float).Value = CDbl(OverTime_RateComboBox.Text)
.Add("#OverTime_Pay", SqlDbType.Float).Value = CDbl(OverTime_PayTextBox.Text)
.Add("#Gross_Salary", SqlDbType.Float).Value = CDbl(Gross_SalaryTextBox.Text)
.Add("#SSS", SqlDbType.Float).Value = CDbl(SSSTextBox.Text)
.Add("#Pagibig", SqlDbType.Float).Value = CDbl(PagibigTextBox.Text)
.Add("#Philhealth", SqlDbType.Float).Value = CDbl(PhilhealthTextBox.Text)
.Add("#Total_Salary_W_Tax", SqlDbType.Float).Value = CDbl(Total_Salary_W_TaxTextBox.Text)
End With
connection.Open()
RetVal = command.ExecuteNonQuery
End Using
If RetVal = 1 Then
MessageBox.Show("Added")
Else
MessageBox.Show("Not Added")
End If
End Sub

Related

VB.NET: Cannot display selected data from access database into datagridview

I have been trying to display selected data from Access database into datagridview on pressing the button but its not displaying any records neither it is showing any error.
Dim third_da As OleDb.OleDbDataAdapter
Dim third_ds As New DataSet
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
con.Open()
Dim cb_two As New OleDb.OleDbCommandBuilder(third_da)
query_three = "SELECT emp_timing.emp_code, emp_timing.day, emp_timing.travel_time, emp_timing.travel_dest,emp_timing.emp_timein,emp_timing.emp_timeout, emp_timing.emp_hours, emp_timing.emp_mins " & _
"FROM emp_timing WHERE (((emp_timing.emp_code)=" & empcode & ") AND ((emp_timing.day) Like '??/" & ComboBox1.Text & "/20" & TextBox9.Text & "'))"
' "WHERE (((emp_timing.emp_code)=22) AND ((emp_timing.day) Like '??/05/2016'))"
third_da = New OleDb.OleDbDataAdapter(query_three, con)
third_da.Fill(third_ds, "ets")
DataGridView1.DataSource = third_ds.Tables("ets")
con.Close()
Dim view As New DataView(third_ds.Tables(0))
source1.DataSource = view
DataGridView1.DataSource = view
DataGridView1.ReadOnly = True
DataGridView1.CancelEdit()
End Sub
Thanks in Advance!
You can change you condition of emp_timing.day field in query like this :
(Month(emp_timing.day) = & ComboBox1.Text &
and Year(emp_timing.day) = "20" & TextBox9.Text & " )
But, I advice you to use the Parameter to avoid SQL injections , like this :
query_three = "SELECT emp_timing.emp_code, emp_timing.day, emp_timing.travel_time, emp_timing.travel_dest,emp_timing.emp_timein,emp_timing.emp_timeout, emp_timing.emp_hours, emp_timing.emp_mins " &
"FROM emp_timing WHERE (((emp_timing.emp_code)= #empcode) AND ((emp_timing.day) BETWEEN #startDate AND #endDate ))"
Dim startDate As New DateTime("20" & TextBox9.Text, ComboBox1.Text, 1)
Dim endDate As DateTime = startDate.AddMonths(1).AddDays(-1)
Dim cmd As New OleDbCommand(query_three, con)
cmd.Parameters.AddWithValue("#empcode", empcode)
cmd.Parameters.AddWithValue("#startDate", startDate.ToString("#yyyy/MM/dd#"))
cmd.Parameters.AddWithValue("#endDate", endDate.ToString("#yyyy/MM/dd#"))
third_da = New OleDb.OleDbDataAdapter(cmd)

Issues with SQL parameters

I am trying to set employees for a company to 'present' if they clock-in/out on the program. The database has a field with the same name and uses a boolean value to store whether someone is or isn't present. I believe my SQL statement is correct. The issue that I continue to get is: "Additional information: No value given for one or more required parameters."
Here is the code that I am using to perform the UPDATE query:
Private Sub btnClockout_Click(sender As Object, e As EventArgs) Handles btnClockout.Click
'SelectedEmployee = lstClockin.FocusedItem.Text
'lblClockinStatusColor.BackColor = Color.Red
'btnClockout.Enabled = False
'btnClockin.Enabled = True
'lblClockinStatus.Text = "Employee is: Clocked Out"
'If txtInfoEmployeeID.Text = "" Then
' MsgBox("You need to select a employee to clock-out.", MsgBoxStyle.Exclamation)
'End If
con.ConnectionString = provider & datafile
con.Open()
sqlstatement = ("UPDATE [EmployeeAccounts] SET [Present] = False WHERE [EmployeeID] = '" & SelectedEmployee & "'")
da = New OleDb.OleDbDataAdapter(sqlstatement, con)
da.Fill(ds, "ClockOutButton")
con.Close()
End Sub
I don't think there is any Boolean type in SQL database. You can use below code.
Private Sub btnClockout_Click(sender As Object, e As EventArgs) Handles btnClockout.Click
SelectedEmployee = lstClockin.FocusedItem.Text
'lblClockinStatusColor.BackColor = Color.Red
'btnClockout.Enabled = False
'btnClockin.Enabled = True
'lblClockinStatus.Text = "Employee is: Clocked Out"
'If txtInfoEmployeeID.Text = "" Then
' MsgBox("You need to select a employee to clock-out.", MsgBoxStyle.Exclamation)
'End If
con.ConnectionString = provider & datafile
con.Open()
sqlstatement = ("UPDATE [EmployeeAccounts] SET [Present] = 'False' WHERE [EmployeeID] = '" & SelectedEmployee & "'")
da = New OleDb.OleDbDataAdapter(sqlstatement, con)
da.Fill(ds, "ClockOutButton")
con.Close()
End Sub

Executing two cmd.commandtext in one line

The program executes one cmd.commandtext at a time. Both of my tables are using the same primary keys which is ID.
How do I execute both cmd.commandtext at the same time?
Imports System.Data
Imports System.Data.OleDb
Public Class Form1
Dim cnnOLEDB As New OleDbConnection
Dim cmdInsert As New OleDbCommand
Dim cmdOLEDB As New OleDbCommand
Dim cmdUpdate As New OleDbCommand
Dim connection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Harry\Documents\Database1.accdb;"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cnnOLEDB.ConnectionString = connection
cnnOLEDB.Open()
End Sub
Private Sub btnReal_Click(sender As Object, e As EventArgs) Handles btnReal.Click
If txtName.Text <> "" And txtId.Text <> "" And txtReceipt.Text <> "" Then
cmdUpdate.CommandText = "UPDATE customer Set Stu_Name = '" & txtName.Text & " ' " & "WHERE ID = " & txtId.Text & " ; "
cmdUpdate.CommandText = "UPDATE admin Set receipt = '" & txtReceipt.Text & " ' " & "WHERE ID = " & txtId.Text & " ; "
cmdUpdate.CommandType = CommandType.Text
cmdUpdate.Connection = cnnOLEDB
cmdUpdate.ExecuteNonQuery()
cmdUpdate.Dispose()
MsgBox(txtName.Text + "Record Updated!")
End If
End Sub
The first thing to say here is: Do not use string concatenation to build sql queries, but use always a parameterized query. Without it you will find a lot of problem like parsing of single quotes in your name or worst an Sql Injection hack. Said that, I suppose that you are using OleDb (probably with an Access database). This scenario doesn't support the execution of multiple command in a single sql statement.
You are forced to call the ExecuteNonQuery two times after changing the command text
Private Sub btnReal_Click(sender As Object, e As EventArgs) Handles btnReal.Click
If txtName.Text <> "" And txtId.Text <> "" And txtReceipt.Text <> "" Then
cmdUpdate.Connection = cnnOLEDB
cmdUpdate.CommandText = "UPDATE customer Set Stu_Name = #name " & _
"WHERE ID = #id"
cmdUpdate.Parameters.Add("#name", OleDbType.VarWChar).Value = txtName.Text
cmdUpdate.Parameters.Add("#id", OleDbType.Integer).Value = Convert.ToInt32(txtId.Text)
cmdUpdate.ExecuteNonQuery()
cmdUpdate.Parameters.Clear()
cmdUpdate.CommandText = "UPDATE admin Set receipt = #recpt " & _
"WHERE ID = #id"
cmdUpdate.Parameters.Add("#recpt", OleDbType.VarWChar).Value = txtReceipt.Text
cmdUpdate.Parameters.Add("#id", OleDbType.Integer).Value = Convert.ToInt32(txtId.Text)
cmdUpdate.ExecuteNonQuery()
End If
End Sub
Not strictly related to your actual problem, but it seems pretty clear from your code that you have a global connection object and also a global command object. Don't do that. You gain very little in terms of performance but you will have problems with disposing connection, keep track of open/closed state and you will consume precious system resources. Always use a local connection object inside a using statement.

Syntax Error in Update Statement in my code

good day, i have the following codes:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim cmd As New OleDb.OleDbCommand
Dim compDate As Date
Dim x As New Integer
Dim profID As New Integer
Dim date1 As New Date
compDate = Format(Date.Now, "hh:mm:ss, tt")
'MsgBox(compDate)
date1 = #8:00:00 AM#
profID = 201400001
x = 1
If Not cnn.State = ConnectionState.Open Then
cnn.Open()
End If
cmd.Connection = cnn
'Timer1.Start()
Timer1.Interval = 5000
sp.Close()
Try
sp.Open()
Catch
sp.Close()
End Try
If TextBox1.Text = "201400001" Then
If DateDiff(DateInterval.Minute, date1, Date.Now) > 5 Then
MsgBox("been here")
cmd.CommandText = "UPDATE test " & _
"SET ProfLog" & x & "" & _
"WHERE ProfID='" & Me.TextBox1.Text & "' AND ProfTime=#" & date1 & "#"
cmd.ExecuteNonQuery()
MsgBox("Did this")
End If
MsgBox("Done!")
ElseIf TextBox1.Text = "201400002" Then
MsgBox("Hello World Again!")
ElseIf TextBox1.Text = "201400003" Then
MsgBox("My Turn!")
End If
TextBox1.Clear()
End Sub
once it reach the cmd.ExecuteNonQuery, a syntax error is being displayed. it says that there is a "Syntax error in UPDATE statement" i would like to know what is the syntax that makes my program go wrong. Thanks in advance.
You have an error in your UPDATE statement. You're missing an = after SET ProfLog:
"UPDATE test " & _
"SET ProfLog = " & x & "" & _
"WHERE ProfID='" & Me.TextBox1.Text & "' AND ProfTime=#" & date1 & "#"
You could have figured this out yourself by showing the cmd.CommandText in a message box or the immediate window in Visual Studio.
Please do yourself a huge favor and search for "parameterized queries" or "SQL injection". You should learn to do things properly from the start, instead of learning to do them poorly and causing yourself many, many problems later.

If or case statement based on radio button click

I am trying to find a way to run some code based on the selection of a radio button. I have several radio buttons in a groupbox which will run different code based on there selection. Now, being a fairly new user to VB.NET, I am struggling to correctly code this.
Would I be better to use an IF statement or a SELECT CASE statement. I have tried using a flag set as a boolean to indicate if button1 is selected, set flag = true. That is as far as I have got. I am using CheckedChanged event to handle to event changes. I have included some code and would be grateful if someone could start me off. Many thanks.
Private Sub rdbBoxReturn_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rdbBoxReturn.CheckedChanged
'code goes here
flagBoxReturn = True
End Sub
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Try
If flagBoxReturn = True Then
MessageBox.Show(CStr(flagBoxReturn))
Return
Else
DBConnection.connect()
sql = "SELECT MAX([Id]) from Request Boxes WHERE Customer = '" & cmbCustomer.Text & "' "
'MessageBox.Show(cmbCustomer.Text)
'sql = "INSERT INTO [Requests] ("")"
'Dim sql As String = "SELECT * from Boxes WHERE Customer = ? AND Status = 'i'"
Dim cmd As New OleDb.OleDbCommand
Dim id As String
Dim requestor As String = "DEMO"
Dim intake As String = "I"
Dim status As String = "O"
'cmd.Parameters.AddWithValue("#p1", cmbCustomer.Text)
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
'lvSelectRequestItems.Items.Clear()
While dr.Read()
id = CStr(CInt(dr.Item(0).ToString))
id = String.Format("{0:D6}", (Convert.ToInt32(id) + 1))
'id = CStr(CDbl(id) + 1)
End While
MessageBox.Show(CStr(id))
dr.Close()
sql = "INSERT INTO [Request Boxes] ([Request no], Customer, Dept, [Type], [Service level], [Date-time received], [Received by], [Date-time due], Quantity, [Cust requestor], Status ) " &
"VALUES ('" & id & "', '" & cmbCustomer.Text.ToUpper & "', '" & cmbDept.Text & "', '" & intake.ToString & "', '" & rbServiceLevel.ToString & "', '" & dtpDateReceived.Value & "', '" & requestor.ToString & "', '" & dtpDateDue.Value & "', '" & txtBoxQuantity.Text & "', '" & requestor.ToString & "', '" & status & "')"
cmd.CommandText = sql
cmd.ExecuteNonQuery()
cmd.Dispose()
oledbCnn.Close()
flagBoxReturn = False
MessageBox.Show("Your record number: " & id & " Was entered successfully")
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
How about something like this...
Public Enum SaveOption As Int32
DoNothing = 0
DoSomething = 1 ' Obviously rename this to something that makes sense in your situation.
End Enum
Public Function GetSaveOption() As SaveOption
Dim result As SaveOption = SaveOption.DoNothing
If rdbBoxReturn.Checked Then
result = DoSomething
End If
' Add as many if statements her to cover all your radio buttons.
Return result
End Function
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Select Case GetSaveOption
Case SaveOption.DoNothing
Exit Sub
Case SaveOption.DoSomething
' Your save code here
End Select
End Sub
This method makes your code more readable by converting UI element states into program states.
Switch statement is better if the number of comparisons is small
if you had a radio button list control, that would be much better as in that case
switch statement can be passed the index variable (SelectedIndex property of the radio
button list) but that control is available in web forms, or can be available in win forms
if you find some free user/custom control etc.
so in your case, better to use if else statements