Query a database and insert if not present - sql

I would like to add a way to see if an entry is already in a connected database in the following code. If it is then don't add the entry and pop up a dialog saying something to the effect of "already been scanned" and if it is not, proceed as usual.
Using connection As New SqlClient.SqlConnection("Data Source=XXXXX;Initial Catalog=XXXXXX;Integrated Security=True;Pooling=False;Encrypt=False"), _
cmd As New SqlClient.SqlCommand("INSERT INTO [XXXXX] (TrackingNumber, Date) SELECT #TrackingNumber, #Date WHERE NOT EXISTS (SELECT * FROM([XXXXX])WHERE TrackingNumber = #TrackingNumber AND Date = #Date)", connection)
cmd.Parameters.Add("#TrackingNumber", SqlDbType.VarChar, 50).Value = TrNum
cmd.Parameters.Add("#Date", SqlDbType.DateTime, 8).Value = TrDate
connection.Open()
cmd.ExecuteNonQuery()
connection.Close()
End Using

You should be able to put your inputs into a subquery that checks for redundancy:
INSERT INTO [XXXXXXX] (TrackingNumber, Date)
SELECT #TrackingNumber, #Date from DUAL
WHERE NOT EXISTS (
SELECT *
FROM [XXXXXXX]
WHERE TrackingNumber = #TrackingNumber AND Date = #Date)

My VB.NET might be somewhat off but hopefully this should give the general idea!
Dim rowsAffected AS Integer
Using connection As New SqlClient.SqlConnection("Data Source=XXXXX;Initial Catalog=XXXXXX;Integrated Security=True;Pooling=False;Encrypt=False"), _
cmd As New SqlClient.SqlCommand("INSERT INTO [XXXXX] (TrackingNumber, Date) SELECT #TrackingNumber, #Date WHERE NOT EXISTS (SELECT * FROM [XXXXX] WHERE TrackingNumber = #TrackingNumber)", connection)
cmd.Parameters.Add("#TrackingNumber", SqlDbType.VarChar, 50).Value = TrNum
cmd.Parameters.Add("#Date", SqlDbType.DateTime, 8).Value = TrDate
connection.Open()
rowsAffected = cmd.ExecuteNonQuery()
connection.Close()
End Using
If rowsAffected = 0 Then
MsgBox "Scanned Already"
Else
MsgBox "Inserted Succesfully"
End If

Related

ExecuteNonQuery returns -1 (incorrectly)

I inherited an old VB Website the uses ExecuteNonQuery to modify passwords. In our production environment, sql server 2008 R2, I've had recent reports of broken functionality. It turns out the ExecuteNonQuery is returning -1 when in fact the data is getting updated (a single row). When I copied the data to our dev environment, the rows affected is 1 as expected. We have a different service packs applied (4XXX vs 6XXX) and I wonder if this is the issue? I modified the code to use ExecuteScalar to inspect the RowCount, and this is working. But I shouldn't have to do so. Any insight? I have now idea how long this has been broken.
Here's the original code, that returns -1 erroneously. It is not calling a stored procedure and there are no triggers involved.
Dim cmd As SqlCommand = New SqlCommand("UPDATE UserMaster " & _
" SET Password = #Password, LastPasswordChangedDate = #LastPasswordChangedDate " & _
" WHERE Username = #UserName AND ApplicationName = #ApplicationName ", conn)
cmd.Parameters.Add("#Password", SqlDbType.VarChar, 255).Value = CreateHash(newPwd)
cmd.Parameters.Add("#LastPasswordChangedDate", SqlDbType.DateTime).Value = DateTime.Now
cmd.Parameters.Add("#Username", SqlDbType.VarChar, 255).Value = username.TrimEnd
cmd.Parameters.Add("#ApplicationName", SqlDbType.VarChar, 255).Value = Left(pApplicationName, 1)
Dim rowsAffected As Integer = 0
Try
conn.Open()
rowsAffected = cmd.ExecuteNonQuery()
This code returns a 1 as expected:
Dim cmd As SqlCommand = New SqlCommand("UPDATE UserMaster " & _
" SET Password = #Password, LastPasswordChangedDate = #LastPasswordChangedDate " & _
" WHERE Username = #UserName AND ApplicationName = #ApplicationName ; select ##rowcount", conn)
cmd.Parameters.Add("#Password", SqlDbType.VarChar, 255).Value = CreateHash(newPwd)
cmd.Parameters.Add("#LastPasswordChangedDate", SqlDbType.DateTime).Value = DateTime.Now
cmd.Parameters.Add("#Username", SqlDbType.VarChar, 255).Value = username.TrimEnd
cmd.Parameters.Add("#ApplicationName", SqlDbType.VarChar, 255).Value = Left(pApplicationName, 1)
Dim rowsAffected As Integer = 0
Try
conn.Open()
rowsAffected = CType(cmd.ExecuteScalar(), Integer)
ExceuteNonQuery returns -1 for all stored procedures as per the Msdn documentation.
It will return the updated records' number only in case of a statement.

Error with searching between two dates on mschart

I have a problem with MSchart control. I have 2 fields on my database for date and time.
When I connect to my database and load X and Y values to my chart, there is no problem, but when i use search between 2 date in my query then mschart loads nothing. I'm using Text format for inDate1 and inTime1, here is my code:
Dim con As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel
Dim query As String = "SELECT inDate1,inTime1 FROM loginlog where personID=" + TextBox1.Text+" and inDate1 between "+ TextBox2.Text " and " + TextBox3.Text
Dim mycon As New OleDbConnection(con)
Dim command As New OleDbCommand(query, mycon)
mycon.Open()
chart1.DataSource = command.ExecuteReader()
chart1.Series(0).XValueMember = "inDate1"
chart1.Series(0).YValueType = ChartValueType.Time
chart1.Series(0).YValueMembers = "inTime1"
chart1.DataBind()
mycon.Close()
You really do not want to use text for dates. Instead, convert them to DateTimes (e.g. with DateTime.TryParse) and pass them as SQL parameters.The remark about passing as an SQL parameter applies to all parameters, including the personID.
So, your code could look something like:
Dim startDate As DateTime
Dim endDate As DateTime
If Not DateTime.TryParse(TextBox2.Text, startDate) Then
' there was an error parsing - do something useful
startDate = New DateTime(2000, 1, 1)
End If
If Not DateTime.TryParse(TextBox3.Text, endDate) Then
' there was an error parsing - do something useful
endDate = New DateTime(2100, 12, 31)
Else
' add a day to include it in the range selected in the SQL query
endDate = endDate.AddDays(1)
End If
Dim query As String = "SELECT inDate1, inTime1 FROM loginlog WHERE personID = #PersonID AND inDate1 BETWEEN #StartDate AND #EndDate"
Dim mycon As New OleDbConnection(con)
Dim command As New OleDbCommand(query, mycon)
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#PersonID", .OleDbType = OleDbType.VarWChar, .Value = TextBox1.Text})
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#StartDate", .OleDbType = OleDbType.Date, .Value = startDate})
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#EndDate", .OleDbType = OleDbType.Date, .Value = endDate})
' now execute the query...

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.

Invalid cast from 'Boolean' to 'DateTime'

I keep getting this error
Invalid cast from 'Boolean' to 'DateTime'
when the codes below try to execute.
I am basically trying to update my auction_item table where the "closedate < todayDate" is met.
This is where the error fires [Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)]
con.Open()
CMD = New SqlCommand("SELECT auction_item_close_date FROM auction_items WHERE (auction_item_status_id = 1)", con)
DR = CMD.ExecuteReader()
DR.Read()
Dim closedate As Date
closedate = Convert.ToDateTime(DR(0))
con.Close()
Dim todayDate As Date = DateAndTime.Today
Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)
con.Open()
If closedate < todayDate Then
SQL = "UPDATE auction_items SET auction_item_status_id = 2, auction_item_open_closed = 'closed' WHERE auction_item_close_date = '" & forupdate & "'"
CMD = New SqlCommand(SQL, con)
CMD.ExecuteNonQuery()
con.Close()
End If
The error is on this line:
Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)
closedate < todayDate returns true or false depending on whether closedate is before todayDate.
That value can not be converted to a DateTime and this is what the exception says. Maybe you need to rethink what the line is supposed to do.

Insert and Select at the same time in a stored procedure

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