VBA + SQL Server - Get Last ID Inserted - sql

Hope you can help - I'm having issues getting the last ID after INSERT.
So the environment - Access 2016, SQL Server and VBA
Dim db As DAO.Database
Dim RS As New ADODB.Recordset
Dim sql As String
I have theses declared and then private sub.
Private Sub CreateOrderHeader()
Dim CustomerID As Integer
Dim OrderDate As String
Dim OrderStatus As String
Dim OrderValue As Double
Dim OrderNotes As String
Dim OrderPostageID As String
Dim OrderAddressID As String
Dim OrderBatchID As Integer
Dim OrderPayment As String
Dim OrderCourierID As String
Dim OrderAgentID As Integer
Dim OrderOutstanding As Double
CustomerID = tbxCusID
OrderDate = Format(Now)
OrderStatus = "InProcess"
OrderValue = txtTotal.value
OrderNotes = tbxNotes.value
OrderPostageID = txtPostage.Column(0)
If tbxCustomerAddress = tbxDeliveryAddress Then
OrderAddressID = 3 'default customers address
Else
'NEED TO GET CUSTOMER ADDRESS TO DO
End If
OrderBatchID = cmbBatch.Column(0)
OrderPayment = sPayMethod
OrderCourierID = cbxShipping.Column(0)
OrderAgentID = 0
OrderOutstanding = txtTotal.value
Dim testvar As String
sql = "INSERT INTO dbo_OrderHeader " _
& "(OrdCusID, OrdDate, OrdStatus, OrdValue, OrdNotes, OrdPostageID, OrdDelAddID,OrdBatchID,OrdPaymentMethod, OrdCourierID,ordAgentID, OrdOutstanding,OrdSource) " _
& " VALUES ('" & CustomerID & "' ,'" & OrderDate & "', '" & OrderStatus & "', '" & OrderValue & "', '" & OrderNotes & "', '" & OrderPostageID & "','" & OrderAddressID & "','" & OrderBatchID & "','" & OrderPayment & "','" & OrderCourierID & "','" & OrderAgentID & "','" & OrderOutstanding & "', 1)"
DoCmd.RunSQL (sql)
sql = "SELECT ##IDENTITY As IDT"
RS.Open sql, CurrentProject.Connection, adOpenStatic, adLockReadOnly
IDT = RS!IDT
MsgBox ("Succes - OrderHeader" & " '" & IDT & "' ")
End Sub
I was expecting a result from this code:
sql = "SELECT ##IDENTITY As IDT"
RS.Open sql, CurrentProject.Connection, adOpenStatic, adLockReadOnly
IDT = RS!IDT
But that gives me "0" as result.
Can you help please.
Thanks

You can try this :
Set db = CurrentDB
db.Execute(sql)
IDT = db.OpenRecordset("SELECT ##IDENTITY")(0)
Set db = Nothing
NOTE
Don't execute your insert query like DoCmd.RunSQL (sql) Instead follow the above approach.

Related

Increase speed of multiple inserts into Access DB from VBA Dictionary

I am attempting to take a VBA Dictionary and either:
Insert a new row into the database if it does not exist
Update the row if it does
While my current code works for this, it runs extremely slowly for the thousands of records I may need to update, and other solutions I have found on this site do not really achieve what I am after. Could anyone help me achieve this? My code so far is below:
Sub UpdateDatabase(dict As Object)
Dim Conn As Object, StrSQL As String, Rs As Object
Dim hmm As ADODB.Recordset
Set Conn = CreateObject("ADODB.Connection")
Conn.Provider = "Microsoft.ACE.OLEDB.12.0"
Conn.Open "C:\XXXX\cfrv2.accdb"
dictCount = dict.Count
counter = 0
For Each varKey In dict.Keys()
Application.StatusBar = Str(counter) & "/" & Str(dictCount)
counter = counter + 1
StrSQL = "SELECT * FROM `All SAMs Backlog` WHERE [LOCID] = '" & varKey & "'"
Set hmm = Conn.Execute(StrSQL)
If hmm.BOF And hmm.EOF Then
StrSQL = "INSERT INTO `ALL SAMs Backlog` ([SAM], [LOCID], [RTC Date], [CFR Status], [CFR Completed Date], [CFR On Hold Reason], [MDU], [ICWB Issue], [Obsolete]) VALUES (dict.Item(varKey)(0), '" & varKey & "', '20/12/2018', '" & dict.Item(varKey)(1) & "', '02/01/2019', '" & dict.Item(varKey)(2) & "' , '" & dict.Item(varKey)(3) & "' , '" &dict.Item(varKey)(4) & "' , '" & dict.Item(varKey)(5) & "')"
Conn.Execute (StrSQL)
Else
'Update the LOC in the table
StrSQL = "UPDATE `All SAMs Backlog` SET ([CFR Status] = '" & dict.Item(varKey)(1) & "', [CFR On Hold Reason] = '" & dict.Item(varKey)(2) & "', [MDU] = '" & dict.Item(varKey)(3) & "', [ICWB Issue] = '" & dict.Item(varKey)(4) & "', [Obsolete] = '" & dict.Item(varKey)(5) & "')"
Conn.Execute (StrSQL)
End If
Next
Conn.Close
End Sub
Any help is appreciated.
Either:
Write the content of the dictionary to a temp table, then run a query as described here:
Update or insert data in table
or:
Open [All SAMs Backlog] as a recordset, loop the dictionary to add or edit records as needed, then close the recordset.

MS Access runtime error 3464

I am working on a database for my work and i'm trying to insert and update values from tables with sql inside the vb editor
This is my code:
Option Compare Database
Private Sub Übernehmen_Click()
Dim strSQL1 As String
Dim strSQL2 As String
Dim strSQL3 As String
Dim ArtikelNr As Integer
Dim Stück As Integer
Dim Lieferant As String
Dim Bestellnr As Integer
Dim EkPreis As String
Dim Mwst As String
Dim Einkaufsort As String
Dim GhIndex As String
Dim Datum As String
Dim Uhrzeit As String
Dim Lager As String
Dim Beschreibung As String
ArtikelNr = [Forms]![Einkauf]![ArtikelNr].Value
Stück = [Forms]![Einkauf]![Stück].Value
Lieferant = [Forms]![Einkauf]![Lieferant].Value
Bestellnr = [Forms]![Einkauf]![Bestellnr].Value
EkPreis = [Forms]![Einkauf]![EK-Preis].Value
Mwst = [Forms]![Einkauf]![Mwst-Satz].Value
Einkaufsort = [Forms]![Einkauf]![Einkaufsort].Value
GhIndex = [Forms]![Einkauf]![GH-Index].Value
Datum = [Forms]![Einkauf]![Datum].Value
Uhrzeit = [Forms]![Einkauf]![Uhrzeit].Value
Lager = [Forms]![Einkauf]![Lager].Value
strSQL1 = "INSERT INTO Einkäufe (ArtikelNr, Stück, Lieferant, Bestellnr, EKPreis, MwstSatz, Einkaufsort, GHIndex) VALUES (" & ArtikelNr & "," & Stück & ",'" & Lieferant & "','" & Bestellnr & "','" & EkPreis & "','" & Mwst & "','" & Einkaufsort & "','" & GhIndex & "');"
Beschreibung = DLast("EinkaufID", "Einkäufe")
strSQL2 = "INSERT INTO Transaktionen VALUES ('" & ArtikelNr & "','" & Datum & "','" & Lager & "','" & Stück & "','EinkaufID ' + '" & Beschreibung & "' ,'Einkauf',NULL,NULL,'" & Uhrzeit & "');"
strSQL3 = "UPDATE Lagerbestand SET Stück = Stück+" & Stück & " WHERE ArtikelNr = '" & ArtikelNr & "' AND Lager = '" & Lager & "';"
DoCmd.RunSQL strSQL1
DoCmd.RunSQL strSQL2
DoCmd.RunSQL strSQL3
End Sub
After trying to press the button it first adds the two entries and stops at the third one just to throw an error saying "Runtime Error: 3464".
After I press debug it marks the line DoCmd.RunSQL strSQL3.
I would appreciate any answer I get.
Many thanks in advance.
A quick google of "Runtime Error 3464" suggests this is a data type mismatch. You'll typically see this when you try to save a date value in a string field or something like that.
Double check the types passed to your SQL statements match the columns they should be saved to - and apply any necessary conversions if you spot differences.
Also one final heads up...by building your SQL string dynamically you are leaving yourself vulnerable to SQL Injection attacks - you should consider using ADOCommands with parameters.
My error was trying to compare an integer with a string. Even though sql does cast it from an integer to a string if you make a new entry, it does not cast it if you want to compare in a where.

Global Variables in SQL statement

I have the following code in VBA:
Dim strSQL As String
strSQL = "UPDATE Workstations SET MID = newvalue WHERE MID = tempvalue"
DoCmd.RunSQL strSQL
newvalue and tempvalue are both global variables and have already been set values. Syntax wise, does this make sense? or am I missing quotation marks?
Try this one:
If MID is number:
Dim strSQL As String
strSQL = "UPDATE Workstations SET [MID] = " & newvalue & " WHERE [MID] = " & tempvalue
DoCmd.RunSQL strSQL
If MID is string (if newvalue/tempvalue doesn't contain single quote '):
Dim strSQL As String
strSQL = "UPDATE Workstations SET [MID] = '" & newvalue & "' WHERE [MID] = '" & tempvalue & "'"
DoCmd.RunSQL strSQL
If MID is string (if newvalue/tempvalue contains single quote ' like newvalue="Mike's car"):
Dim strSQL As String
strSQL = "UPDATE Workstations SET [MID] = '" & Replace(newvalue, "'", "''") & "' WHERE [MID] = '" & Replace(tempvalue, "'", "''") & "'"
DoCmd.RunSQL strSQL
If MID is date:
Dim strSQL As String
strSQL = "UPDATE Workstations SET [MID] = #" & newvalue & "# WHERE [MID] = #" & tempvalue & "#"
DoCmd.RunSQL strSQL
Thanks to #HansUp for pointing out in comments, that
MID is the name of a function, so it would be safer to bracket or alias that field name in the SQL statement: SET [MID]

Updating Access Database using UPDATE SQL statement in VBA

Can someone take a look a the stSQL string and help me fix the syntax error I am getting associated with the UPDATE statement?
Run-time error '-2147217900 (8004e14)': Syntax error in UPDATE statement.
I have a rudimentary understanding of SQL and don't seem to understand where I have gone wrong.
I want to update the fields of Table 1 if the FileName UserForm value matches a FileName field in the Access Db.
Thanks
Public Sub UpdateDatabaseEntry()
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim stDB As String, stSQL As String, stProvider As String
Dim FileName As String
Dim Nickname As String
Dim RecipientName As String
Dim RecipientRelationship As String
Dim Summary As String
Dim Noteworthy As String
Dim PreparedBy As String
FileName = UserForm1.FileNameTextBox.Text
Nickname = UserForm1.NicknameTextBox.Text
RecipientName = UserForm1.RecipientNameTextBox.Text
RecipientRelationship = UserForm1.RecipientRelationshipComboBox.Text
Summary = UserForm1.SummaryTextBox.Text
Noteworthy = UserForm1.NoteworthyCheckBox.Value
PreparedBy = UserForm1.PreparedByTextBox.Text
stDB = "Data Source= E:\MyDb.accdb"
stProvider = "Microsoft.ACE.OLEDB.12.0"
//Opening connection to database
With cn
.ConnectionString = stDB
.Provider = stProvider
.Open
End With
//SQL Statement telling database what to do
stSQL = "UPDATE Table1" & _
"SET Nickname= '" & Nickname & "', RecipientName= '" & RecipientName & "', " & _
"RecipientRelationship= '" & RecipientRelationship & "', Summary= '" & Summary & "', " & _
"Noteworthy= '" & Noteworthy & "', PreparedBy= '" & PreparedBy & "', " & _
"WHERE FileName= '" & FileName & "'"
cn.Execute stSQL
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
At least one problem is caused by lack of spaces in the query. So your query started UPDATE Table1set.
stSQL = "UPDATE Table1 " & _
"SET Nickname= '" & Nickname & "', RecipientName= '" & RecipientName & "', " & _
"RecipientRelationship= '" & RecipientRelationship & "', Summary= '" & Summary & "', " & _
"Noteworthy= '" & Noteworthy & "', PreparedBy= '" & PreparedBy & "'" & _
"WHERE FileName= '" & FileName & "'"
If this doesn't fix the problem. Then edit your question with the value of stSQL after the variable substitution.
EDIT:
As TS points out, another problem is the , before the where (fixed above).

How to insert customer details into Orders table

I have an assignment to build a basic database driven e-commerce site. I have a home page, a products page, an orders page, an order confirm page, a shopping cart page and a view current orders page. The site uses an Access database with three tables.
A Customer table, with all of the customer details, (FirstName, LastName, EmailAdd, CardNo, CardEx, SortCode, DeliveryAdd, Postcode)
A Products table, with all the product information, (ProductID, ProductName, Price, ProductType, Images, ProductDescription).
And an Orders table which contains CustomerID and ProductID.
I'm trying to create an INSERT statement on the orders page so that when the customer inserts their details and presses the submit button the customers table will have a new record inserted. I also want this to create an entry in the orders table and redirect the client to the order confirm page which will display the details of the order.
Here is my code which runs when the submit button is clicked on the order form.
EDIT I've fixed the error with the missing apostrophe. Attempting to insert using two sql commands as I've been told that access databases can't handle two at once. Still getting an error though.
Protected Sub btnAddRecord_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim strFirstName As String
Dim strLastName As String
Dim strEmailAdd As String
Dim intCardNo As String
Dim strCardEx As String
Dim intSortCode As String
Dim strDeliveryAdd As String
Dim strPostCode As String
Dim intProductID As Integer
strFirstName = tbxFirstName.Text
strLastName = tbxLastName.Text
strEmailAdd = tbxEmailAdd.Text
intCardNo = tbxCardNo.Text
strCardEx = tbxCardEx.Text
intSortCode = tbxSortCode.Text
strDeliveryAdd = tbxDeliveryAdd.Text
strPostCode = tbxPostcode.Text
intProductID = ddlProduct.SelectedValue
Dim strDatabaseNameAndLocation As String
strDatabaseNameAndLocation = Server.MapPath("KingToots.mdb")
Dim strSQLCommand As String
strSQLCommand = "INSERT INTO Customer(FirstName, LastName, EmailAdd, CardNo, CardEx, SortCode, DeliveryAdd, Postcode) " & _
"Values ('" & strFirstName & "', '" & strLastName & "', '" & strEmailAdd & "', '" & intCardNo & "', '" & strCardEx & "', '" & intSortCode & "', '" & strDeliveryAdd & "', '" & strPostCode & "');"
Dim objOleDbConnection As System.Data.OleDb.OleDbConnection
objOleDbConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0; Data Source=" & strDatabaseNameAndLocation)
objOleDbConnection.Open()
Dim objOleDbCommand As System.Data.OleDb.OleDbCommand
objOleDbCommand = New System.Data.OleDb.OleDbCommand(strSQLCommand, objOleDbConnection)
objOleDbCommand.ExecuteNonQuery()
objOleDbConnection.Close()
strSQLCommand = "INSERT INTO Orders(ProductID) " & "Values ('" & intProductID & "');"
objOleDbConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0; Data Source=" & strDatabaseNameAndLocation)
objOleDbConnection.Open()
objOleDbCommand = New System.Data.OleDb.OleDbCommand(strSQLCommand, objOleDbConnection)
objOleDbCommand.ExecuteNonQuery()
objOleDbConnection.Close()
strSQLCommand = "SELECT Customer.* FROM Customer ORDER BY Customer.CustomerID DESC;"
objOleDbConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0; Data Source=" & strDatabaseNameAndLocation)
objOleDbConnection.Open()
objOleDbCommand = New System.Data.OleDb.OleDbCommand(strSQLCommand, objOleDbConnection)
Dim objOleDbDataReader As System.Data.OleDb.OleDbDataReader
objOleDbDataReader = objOleDbCommand.ExecuteReader()
Dim datDataTable As System.Data.DataTable
datDataTable = New System.Data.DataTable()
datDataTable.Load(objOleDbDataReader)
objOleDbConnection.Close()
tbxFirstName.Text = ""
tbxLastName.Text = ""
tbxEmailAdd.Text = ""
tbxCardNo.Text = ""
tbxCardEx.Text = ""
tbxSortCode.Text = ""
tbxDeliveryAdd.Text = ""
tbxPostcode.Text = ""
End Sub
You're missing the closing quotes at the end of this line:
strSQLCommand = "INSERT INTO Customer(FirstName, LastName, EmailAdd, CardNo, CardEx, SortCode, DeliveryAdd, Postcode) " & _
"Values ('" & strFirstName & "', '" & strLastName & "', '" & strEmailAdd & "', '" & intCardNo & "', '" & strCardEx & "', '" & intSortCode & "', '" & strDeliveryAdd & "', '" & strPostCode & ");"
About the obvious SQL injection problem, switching to parameters would be the best way to do it (and you'd never have your original issue if you did, parameters don't use quotes), but at the very least run a replace on your strings to replace ' with '' so your program doesn't just die if you get a customer called O'Neil.
He is correct, you don't want to do this you will get sql injection. But here is the solution to your problem anyway.
The problem is not in the last sql statement but in the previous one.
'" & strPostCode & " is missing the last single quote.
it should read:
'" & strPostCode & "');