Quickest Way to Add New Rows to Datatable That Could Contain Duplicates - sql

I have a table full of stock price data. Each row has a unique combination of Ticker symbols and dates. I load new data all the time by obtaining CSV files containing stock price data for everyday for every ticker. I know that there are duplicates in the CSV files. I only want to add that data that is not already in my data table. What is the quickest way to do this?
Should I try to add every row and catch each exception? Or, should I compare each row against my data table by reading my data table to see that line already exists? Or, is there another alternative?
Additional Info
This is what I have been doing. For each line in the CSV file I read my data table to see if it already exists.
Dim strURL As String
Dim strBuffer As String
strURL = "http://ichart.yahoo.com/table.csv?s=" & tickerValue
strBuffer = RequestWebData(strURL)
Dim sReader As New StringReader(strBuffer)
Dim List As New List(Of String)
Do While sReader.Peek >= 0
List.Add(sReader.ReadLine)
Loop
List.RemoveAt(0)
Dim lines As String() = List.ToArray
sReader.Close()
For Each line In lines
Dim checkDate = line.Split(",")(0).Trim()
Dim dr As OleDbDataReader
Dim cmd2 As New OleDb.OleDbCommand("SELECT * FROM " & tblName & " WHERE Ticker = ? AND [Date] = ?", con)
cmd2.Parameters.AddWithValue("?", tickerValue)
cmd2.Parameters.AddWithValue("?", checkDate)
dr = cmd2.ExecuteReader
If dr.Read() = 0 Then
Dim cmd3 As OleDbCommand = New OleDbCommand("INSERT INTO " & tblName & " (Ticker, [Date], [Open], High, Low, [Close], Volume, Adj_Close) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", con)
cmd3.Parameters.Add("#Ticker", OleDbType.VarChar).Value = tickerValue
cmd3.Parameters.Add("#[Date]", OleDbType.VarChar).Value = checkDate
cmd3.Parameters.Add("#[Open]", OleDbType.VarChar).Value = line.Split(",")(1).Trim
cmd3.Parameters.Add("#High", OleDbType.VarChar).Value = line.Split(",")(2).Trim
cmd3.Parameters.Add("#Low", OleDbType.VarChar).Value = line.Split(",")(3).Trim
cmd3.Parameters.Add("#[Close]", OleDbType.VarChar).Value = line.Split(",")(4).Trim
cmd3.Parameters.Add("#Volume", OleDbType.VarChar).Value = line.Split(",")(5).Trim
cmd3.Parameters.Add("#Adj_Close", OleDbType.VarChar).Value = line.Split(",")(6).Trim
cmd3.ExecuteNonQuery()
Else
End If
This is what I have switched to and it gives this exception: The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again. I could catch this exception every time and ignore it until I hit a line that is new.
Dim strURL As String = "http://ichart.yahoo.com/table.csv?s=" & tickerValue
Debug.WriteLine(strURL)
Dim strBuffer As String = RequestWebData(strURL)
Using streamReader = New StringReader(strBuffer)
Using reader = New CsvReader(streamReader)
reader.ReadHeaderRecord()
While reader.HasMoreRecords
Dim dataRecord As DataRecord = reader.ReadDataRecord()
Dim cmd3 As OleDbCommand = New OleDbCommand("INSERT INTO " & tblName & " (Ticker, [Date], [Open], High, Low, [Close], Volume, Adj_Close) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", con)
cmd3.Parameters.Add("#Ticker", OleDbType.VarChar).Value = tickerValue
cmd3.Parameters.Add("#[Date]", OleDbType.VarChar).Value = dataRecord.Item("Date")
cmd3.Parameters.Add("#[Open]", OleDbType.VarChar).Value = dataRecord.Item("Open")
cmd3.Parameters.Add("#High", OleDbType.VarChar).Value = dataRecord.Item("High")
cmd3.Parameters.Add("#Low", OleDbType.VarChar).Value = dataRecord.Item("Low")
cmd3.Parameters.Add("#[Close]", OleDbType.VarChar).Value = dataRecord.Item("Close")
cmd3.Parameters.Add("#Volume", OleDbType.VarChar).Value = dataRecord.Item("Volume")
cmd3.Parameters.Add("#Adj_Close", OleDbType.VarChar).Value = dataRecord.Item("Adj Close")
cmd3.ExecuteNonQuery()
End While
End Using
End Using
I just want to use the most efficient method.
Update
Per the answers below, this is the code I have so far:
Dim strURL As String = "http://ichart.yahoo.com/table.csv?s=" & tickerValue
Dim strBuffer As String = RequestWebData(strURL)
Using streamReader = New StringReader(strBuffer)
Using reader = New CsvReader(streamReader)
' the CSV file has a header record, so we read that first
reader.ReadHeaderRecord()
While reader.HasMoreRecords
Dim dataRecord As DataRecord = reader.ReadDataRecord()
Dim cmd3 As OleDbCommand = New OleDbCommand("INSERT INTO " & tblName & "(Ticker, [Date], [Open], High, Low, [Close], Volume, Adj_Close) " & "SELECT ?, ?, ?, ?, ?, ?, ?, ? " & "FROM DUAL " & "WHERE NOT EXISTS (SELECT 1 FROM " & tblName & " WHERE Ticker = ? AND [Date] = ?)", con)
cmd3.Parameters.Add("#Ticker", OleDbType.VarChar).Value = tickerValue
cmd3.Parameters.Add("#[Date]", OleDbType.VarChar).Value = dataRecord.Item("Date")
cmd3.Parameters.Add("#[Open]", OleDbType.VarChar).Value = dataRecord.Item("Open")
cmd3.Parameters.Add("#High", OleDbType.VarChar).Value = dataRecord.Item("High")
cmd3.Parameters.Add("#Low", OleDbType.VarChar).Value = dataRecord.Item("Low")
cmd3.Parameters.Add("#[Close]", OleDbType.VarChar).Value = dataRecord.Item("Close")
cmd3.Parameters.Add("#Volume", OleDbType.VarChar).Value = dataRecord.Item("Volume")
cmd3.Parameters.Add("#Adj_Close", OleDbType.VarChar).Value = dataRecord.Item("Adj Close")
cmd3.Parameters.Add("#Ticker", OleDbType.VarChar).Value = tickerValue
cmd3.Parameters.Add("#[Date]", OleDbType.VarChar).Value = dataRecord.Item("Date")
cmd3.ExecuteNonQuery()
End While
End Using
End Using
It gives me this error Data type mismatch in criteria expression.

Most DBMS support a (non-standard) clause for the INSERT command to ignore duplicates, e.g.:
MySQL: INSERT IGNORE INTO ...
SQLite: INSERT OR IGNORE INTO INTO ...
This is the quickest way in non-batch mode, as you don't have to read the database before you write.
You can do the same with standard SQL using:
INSERT INTO ...
SELECT <your values>
WHERE NOT EXISTS ( <query for your values by id> );
Or (when you explicitly need a FROM clause):
INSERT INTO ...
SELECT <your values>
FROM DUAL
WHERE NOT EXISTS ( <query for your values by id> );
EDIT
MS Access does not have a built-in DUAL table (i.e., a table that always contains just one single row), but Access requires a FROM clause. So you have to build your own DUAL table:
CREATE TABLE DUAL (DUMMY INTEGER);
INSERT INTO DUAL VALUES (1);
You just do this once and for all. Then, in your code you would do inserts like
INSERT INTO MyTable (A,B,C,D)
SELECT 123, 456, 'Hello', 'World'
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM MyTable WHERE A = 123 AND B = 456);
Thus, for your example, use:
Dim cmd3 As OleDbCommand = New OleDbCommand(_
"INSERT INTO " & tblName & _
"(Ticker, [Date], [Open], High, Low, [Close], Volume, Adj_Close) " & _
"SELECT ?, ?, ?, ?, ?, ?, ?, ? " & _
"FROM DUAL " & _
"WHERE NOT EXISTS (SELECT 1 FROM tblName WHERE Ticker = ? AND [Date] = ? AND ...)", con)
(WHERE clause depending on your key columns)

Related

Getting error on inserting date into sql database?

I'm inserting record into database but is getting error on the paremeter "Date". Any thoughts would be good.
myConnection.Open()
Dim sqlQry As String = "INSERT INTO MasterLabNumber (LabNumber, Location, Date)" + "VALUES(#LabNumber, #Location, #Date)"
Dim str As String
str = "SELECT * FROM MasterLabNumber WHERE (LabNumber = " & TextBox1.Text & ")"
Dim d As System.DateTime = DateTime.Now.ToString("yyyy/MM/dd")
Dim cmd As OleDbCommand = New OleDbCommand(sqlQry, myConnection)
cmd.Parameters.AddWithValue("#LabNumber", TextBox1.Text)
cmd.Parameters.AddWithValue("#Location", ComboBox1.Text)
cmd.Parameters.AddWithValue("#Date", d)
cmd.ExecuteNonQuery() <-- gets error here relating to adding the parameter date.
Yeah, that's cause Date is a reserve word which you are using in your insert statement. You need to escape it like below using []
INSERT INTO MasterLabNumber (LabNumber, Location, [Date])
Your insert statement should become
Dim sqlQry As String = "INSERT INTO MasterLabNumber (LabNumber, Location, [Date]) VALUES(#LabNumber, #Location, #Date)"

SQL transaction statement in vb.net

I'm making a project that is linked to Microsoft SQLServer, used to enter, remove, edit data about customers and orders. The full system works, however I've been advised to use transactions rather than regular SQL statements to add/remove/edit data etc.
The trouble is, I've not used these before and from my research over the last few hours, I can't work out how to even begin them.
Can anybody advise me how to turn the following code into a transaction?
Public Shared Function SaveNewPerson(ByVal firstName As String, lastName As String, ByVal age As Integer, ByVal postcode As String, m_cn As OleDbConnection)
Dim Dc As New OleDbCommand
Dc.Connection = m_cn
m_cn.Open()
Dc.CommandText = "INSERT INTO tblPerson([firstName], [lastName], [age], [postcode]) VALUES('" & firstName & "', '" & lastName & "', '" & age & "', '" & postcode & "')"
Dc.ExecuteNonQuery()
Dim personID As Integer
Dc.CommandText = "SELECT ##IDENTITY"
Dc.CommandType = CommandType.Text
personID = CType(Dc.ExecuteScalar(), Integer)
m_cn.Close()
End Function
I've just been learning TSQL, see if this sort of code will work for you (note that you need to Dim tr (with a different variable name, if you like) and use it in multiple places, but unlike in some languages you don't need to set up objects for the different methods.
Public Shared Function SaveNewIncident(ByVal clientName As String, dateStart As Date, dateEnd As Date, ByVal incidentProblem As String, ByVal timeStart As String, ByVal timeEnd As String,
ByVal incidentSolved As Boolean, ByVal incidentSolution As String, _con As OleDbConnection)
Dim tr As OleDbTransaction = Nothing
Try
Dim Dc As New OleDbCommand
Dc.Connection = _con
tr = _con.BeginTransaction()
Dc.CommandType = CommandType.Text
Dc.CommandText = "INSERT INTO dbo.tblIncidents VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"
Dc.Transaction = tr
Dc.Parameters.Add("#clientName", OleDbType.VarChar).Value = clientName
Dc.Parameters.Add("#dateStart", OleDbType.Date).Value = dateStart
Dc.Parameters.Add("#dateEnd", OleDbType.Date).Value = dateEnd
Dc.Parameters.Add("#incidentProblem", OleDbType.LongVarChar).Value = incidentProblem
Dc.Parameters.Add("#timeStart", OleDbType.VarChar).Value = timeStart
Dc.Parameters.Add("#timeEnd", OleDbType.VarChar).Value = timeEnd
Dc.Parameters.Add("#incidentSolved", OleDbType.Boolean).Value = incidentSolved
Dc.Parameters.Add("#incidentSolution", OleDbType.LongVarChar).Value = incidentSolution
Dim personID As Integer
Dc.CommandText = "SELECT SCOPE_IDENTITY() AS personID"
Dc.CommandType = CommandType.Text
personID = CType(Dc.ExecuteScalar(), Integer)
tr.Commit()
Catch ex As Exception
tr.Rollback()
Throw
End Try
End Function

Operator not defined error?

I am trying to update a record but I get the error: Operator '=' is not defined for type 'Date' and type 'Integer'. How can I fix this?
If Me.txt_Team.Tag = 0 Then
sSQL = "INSERT INTO FixtureandResultsDatabase (Fixture_Date, Team, Ground, Score)"
sSQL = sSQL & " VALUES(?, ?, ?, ?)"
cmd.CommandText = sSQL
Else
sSQL = "UPDATE FixtureandResultsDatabase set Fixture_Date = #Fixture_Date, Team = #Team, Ground = #Ground, Score = #Score WHERE ID = #id"
cmd.CommandText = sSQL
End If
cmd.Parameters.Add("#Fixture_Date", OleDbType.Date).Value = Me.dtp_Date.Text
cmd.Parameters.Add("#Team", OleDbType.VarChar).Value = Me.txt_Team.Text
cmd.Parameters.Add("#Ground", OleDbType.VarChar).Value = Me.cb_Ground.Text
cmd.Parameters.Add("#Score", OleDbType.VarChar).Value = Me.txt_Score.Text
If Me.txt_Team.Tag <> 0 Then
cmd.Parameters.Add("#ID", OleDbType.Numeric).Value = Me.txt_Team.Tag
End If
cmd.ExecuteNonQuery()
If Me.txt_Team.Tag = 0 Then
cmd.Parameters.Clear()
cmd.CommandText = "Select ##Identity"
Me.txt_Team.Tag = cmd.ExecuteScalar()
End If
MsgBox("Database has been updated.")
conn.Close()
Fix it like this
Instead of
cmd.Parameters.Add("#Fixture_Date", OleDbType.Date).Value = Me.dtp_Date.Text
Do
cmd.Parameters.Add("#Fixture_Date", OleDbType.Date).Value = Me.dtp_Date.Value
You should post your table structure [sp_help 'tableName']. You obviously have date field but you trying to set value [object] to string - Me.dtp_Date.Text.
On another note - get rid OleDB ASAP - use SqlClient. oleDb will be decommissioned soon. Also, you can use Output Inserted.Id in your update and insert with ExecuteScalar instead of ExecuteNonQuery. It will return your identity all in one statement - instead of Select ##Identity.

Update sqlite query not working in Visual Basic 2013

I am trying to insert row and update row (if row already exists), as following -
Dim con As SQLiteConnection
Dim sql As String
Dim cmd As New SQLiteCommand
Dim da As SQLiteDataAdapter
Dim ds As New DataSet
Dim NumberOfRows As Integer
Public Sub UpdateUserStatistics(ByVal UserId As Integer, ByVal QId As Integer, _
ByVal KeyName As String, ByVal KeyValue As Integer)
con = New SQLiteConnection("Data Source = " + AppDomain.CurrentDomain.BaseDirectory + "/user_statistics.db;Version=3;")
con.Open()
sql = "SELECT * FROM med_user_meta where user_id=" & UserId & " And qid=" & QId
da = New SQLiteDataAdapter(sql, con)
da.Fill(ds, "UserMeta")
NumberOfRows = ds.Tables("UserMeta").Rows.Count
ds.Clear()
If (NumberOfRows = 0) Then
Dim InsertQuery As SQLiteCommand = con.CreateCommand
InsertQuery.CommandText = "INSERT INTO med_user_meta " _
& "(user_id, qid, " _
& KeyName _
& ", timestamp) VALUES(?, ?, ?, datetime('now'))"
InsertQuery.Parameters.AddWithValue("user_id", UserId)
InsertQuery.Parameters.AddWithValue("qid", QId)
InsertQuery.Parameters.AddWithValue(KeyName, KeyValue)
RowInserted = InsertQuery.ExecuteNonQuery()
ElseIf (NumberOfRows = 1) Then
Dim UpdateQuery As SQLiteCommand = con.CreateCommand
UpdateQuery.CommandText = "UPDATE med_user_meta SET " _
& KeyName _
& " = ?, timestamp = datetime('now') Where qid = ?"
'UpdateQuery.Parameters.AddWithValue("user_id", UserId)
UpdateQuery.Parameters.AddWithValue("qid", QId)
UpdateQuery.Parameters.AddWithValue(KeyName, KeyValue)
RowUpdated = UpdateQuery.ExecuteNonQuery()
End If
con.Close()
End Sub
I am using this code in a module and calling UpdateUserStatistics wherever required
My problem is that, insert query works fine, but update query does Not work.
It's been more than 2 hours, but I couldn't find, where am I making mistake?
Also, is there any way to get the final update query into message box after adding parameters, so that I can check if my final update query is correct?
Edit - 1
I forgot to mention, value of RowUpdated is returning 0, i.e. ExecuteNonQuery is Not updating the row.
I have also confirmed that row corresponding to update query Do exists, and the ElseIf (NumberOfRows = 1) Then block is running too, but it's Not updating the row.

How to Insert data while Copying data in other Table

My problem is, in one button (click event) I need to Copy a data in Table1 (the ToolName) to Table2 (into ToolName) and insert a description to the same row.
Table1
ID - ToolName - Quantity
Table2
ID - ToolName - Description
here`s my codes
Dim sqlquery As String = "INSERT INTO Table2 (ToolName) SELECT ToolName FROM Table1 WHERE ID = '" & DataGridView1.CurrentRow.Cells(0).Value.ToString & "' INSERT INTO Table2 (Description) VALUES ('" & TextBox1.Text & "')"
Dim cmd As New OleDbCommand(sqlquery, con)
con.Open()
cmd.ExecuteNonQuery()
MsgBox(" succesfully", vbInformation)
con.Close()
Parametrized queries have two main advantages:
Security: It is a good way to avoid SQL Injection vulnerabilities
Performance: If you regularly invoke the same query just with different parameters a parametrized query might allow the database to cache your queries which is a considerable source of performance gain.
Extra: You won't have to worry about date and time formatting issues in your database code. Similarly, if your code will ever run on machines with a non-English locale, you will not have problems with decimal points / decimal commas.
Try like this
Dim sqlquery As String= "INSERT INTO Table2 (ToolName,Descrption) SELECT ToolName,#Desc FROM Table1 WHERE ID = #Id"
Dim cmd As New OleDbCommand(sqlquery, con)
cmd.Parameters.Add("#Desc", SqlDbType.VarChar, 50).Value = TextBox1.Text
cmd.Parameters.Add("#Id", SqlDbType.VarChar, 50).Value = DataGridView1.CurrentRow.Cells(0).Value.ToString
con.Open()
cmd.ExecuteNonQuery()
MsgBox("succesfully", vbInformation)
con.Close()
Change Query syntax like below
Dim sqlquery As String = "INSERT INTO Table2 (ToolName)
SELECT ToolName FROM Table1
WHERE ID = '" & DataGridView1.CurrentRow.Cells(0).Value.ToString & "';
INSERT INTO Table2 (Description) VALUES ('" & TextBox1.Text & "')"
I think nothing is wrong in query just missing ; between 2 insert query.
Just break it down into two separate updates based on what you already have, use the following code and just pass the ToolName into your update statements
Dim Table_ As String = "getToolName"
Dim query As String = "SELECT ToolName FROM Table1 WHERE ID = '" & DataGridView1.CurrentRow.Cells(0).Value.ToString
Dim cmd As New OleDbCommand(query, con)
Dim da As New OleDbDataAdapter(cmd)
da.Fill(ds, Table_)
Dim dt As DataTable = ds.Tables(Table_)
Dim ToolName As String = dt.Rows(0)(0).ToString()