Using OLEDB and SQl to interact with an access database, and I need to update one column of the database however there is an error
This is made in vb.net.
I have made sure they are being set in the correct order based off of my database
Dim sql As String = "UPDATE UserInfo SET Password=?, CurrentLevel=? WHERE Username=?" & LoggedInUsername 'TheSQL/DDL code to update
Dim comd As New OleDb.OleDbCommand(sql, Connstring) ' create a COMMAND for this SQL
'set up all the parameters needed but they must be set in the same order as used in SQL
MsgBox(Dlevel & " 1 Is Working")
' comd.Parameters.AddWithValue("#Username", LoggedInUsername)
comd.Parameters.AddWithValue("#Password", LoggedInPassword)
comd.Parameters.AddWithValue("#CurrentLevel", Dlevel)
MsgBox(Dlevel & " 2 Is Working")
comd.ExecuteNonQuery() 'Execute the command
It should update the database to change the Current Level. I have used message boxes to find where the problem is and it is when the command is being executed
Related
I am just starting to move our Access DB to SQL Server and am having trouble.
I have a stored procedure that successfully returns rows to an ado recordset.
When I try to bind the rs containing the results of the stored procedure to the Access form, Access crashes without displaying any error messages. I'm on O365 32b and SQL Server 2019.
Here's the code:
Dim sSQL As String, rs As ADODB.Recordset
1 sSQL = "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
2 ADOConn.ConnectionString = conADO
4 ADOConn.Open
6 Set rs = New ADODB.Recordset
7 rs.CursorLocation = adUseClient
8 rs.Open sSQL, ADOConn
10 Set Me.Recordset = rs ' Access crashes here
. . .
Any help would be greatly appreciated!
tia.
SR
Ok, are you previous using ADO, or are you just introducing this?
In most cases, you are better off to just use a view. (replace the access query with a linked view), and then continue useing client side where clauses or filters (access will ONLY pull down the rows you request). So linked views are often a better choice and much less work (in fact, even existing filter for a open report etc. will work and only critera matching the were clause records are pulled.
And in most cases, i don't introduce ADO.
So for a PT query, I often do this:
dim rs as DAO.RecordSet
with CurrentDb.queryDefs("qryPt")
.SQL = "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
set rs = .OpenRecordSet
end with
So, above assumes you have a pt query called qryPt. This also means that you never deal with or worry about connection strings in code. The pt query has the connection. (and your re-link code now can re-link tables and pt queries).
I ONLY suggest the above as a FYI in case that you introducing ADO for calling store procedures, and the rest of the application was previous DAO. If the application was previous DAO, then leave it alone, and use above approach for your PT queries - even code that needs to call store procedures.
Access tends to try and parse the query text to get filters/sorts/etc to work, and if it isn't a plain syntax error but isn't Access SQL either, strange things tend to happen, mostly crashes.
Try adding a comment up front to make sure Access knows not to parse:
sSQL = "-- Access no parse pls" & vbCrLf & "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
The content of the comment is not relevant, of course, its purpose is to immediately cause a syntax error when Access tries to parse it as Access SQL (which doesn't have comments)
I can't seem to find any good reference or example of how to get this to work. I have a database which is stored on an AS/400 (my local MS Access database [stored on a network drive] has linked tables to the 400, using ODBC/DSN). My utility works just fine passing SQL statements to through Access to retrieve data from the 400 using the linked tables. The problem is that with some of the larger reports and the fact that the 400 is several states away, it can take several hours to run the reports. The settled on solution to this is to create a local "copy" of the tables needed with just the data set that is relevant to the reports, which is a considerably smaller data set. Obviously this has the down side of not being "live" data but I can live with that. Ultimately what I want to do is gather the relevant data from the linked table and save it to separate database that is local to the client so that it could be used if offsite/offline and to increase the speed of the report.
network location stored database = DB1 (Tabled linked to AS/400)
local client stored database = DB2 (relevant data set created by below SQL, non-linked tables named the same as the linked tables)
Below is the SQL statement that I'm trying to get to work using VBA & DAO
SELECT
DB1_TABLEA.FIELD1,
DB1_TABLEA.FIELD2,
DB1_TABLEA.FIELD3,
DB1_TABLEA.FIELD4,
DB1_TABLEA.FIELD5,
DB1_TABLEA.FIELD6,
DB1_TABLEA.FIELD7,
DB1_TABLEA.FIELD8
INTO
DB1_TABLEA IN 'Local_DB_Copy.accdb' <== Creating non-linked copy
FROM
DB1_TABLEA
WHERE
(
((DB1_TABLEA.FIELD4) Like 99999)
AND
((DB1_TABLEA.FIELD6)="02" Or (DB1_TABLEA.FIELD6)="22")
)
;
I already have my program working fine and returning/processing data from the AS/400 DB. I just need to be able to get the above to work so that people have the option to run a local copy that will process much faster.
Below is the code that I tried, but of course it fails or I wouldn't be here.
Sub gCreateLocalDBTables()
Dim DBPath As String
Dim LocalDBPath As String
Dim sSQL As String
Dim DB As DAO.Database
Dim DB2 As DAO.Database
Dim RS As DAO.Recordset
LocalDBPath = "AS400_Local.accdb"
sSQL = "SELECT DB1_TABLEA.FIELD1, DB1_TABLEA.FIELD2, DB1_TABLEA.FIELD3, DB1_TABLEA.FIELD4, DB1_TABLEA.FIELD5, DB1_TABLEA.FIELD6, DB1_TABLEA.FIELD7, DB1_TABLEA.FIELD8 INTO DB2_TABLEA IN '" & LocalDBPath & "' FROM DB1_TABLEA WHERE (((DB1_TABLEA.FIELD4) Like 99999) AND ((DB1_TABLEA.FIELD6)='02' Or (DB1_TABLEA.FIELD6)='22'));"
Set DB = OpenDatabase(LocalDBPath, False, False)
DB.TableDefs.Delete ("DB2_TABLEA")
DB.Close
DBPath = Interaction.GetSetting("Cust_Tools", "Settings\Report_Planning", "400DB_Location")
Set DB2 = OpenDatabase(DBPath, False, False)
Set RS = DB2.OpenRecordset(sSQL)
RS.Close
DB2.Close
Set RS = Nothing
Set DB = Nothing
Set DB2 = Nothing
End Sub
I know the SQL works as I have tested it from inside MS Access. I just can't find info on how to get it to work being passed from Excel VBA
You cannot assign an action query like a make-table query (i.e., SELECT with INTO call) to a recordset. Consider executing your DROP and SELECT ... INTO action queries prior to opening recordset on the local table. Also, it is unclear why you are opening a second database or what the path points to. Below opens a recordset on the mainframe data:
Set DB = OpenDatabase(LocalDBPath, False, False)
DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute sSQL, dbFailOnError
Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")
Furthermore, the IN clause in your make-table query is unnecessary as you are currently connected to the very database you are running the action on. Simply remove it ('" & LocalDBPath & "'). Also, LIKE expressions without wildcards and on numbers should be replaced with =
SELECT
DB1_TABLEA.FIELD1,
DB1_TABLEA.FIELD2,
DB1_TABLEA.FIELD3,
DB1_TABLEA.FIELD4,
DB1_TABLEA.FIELD5,
DB1_TABLEA.FIELD6,
DB1_TABLEA.FIELD7,
DB1_TABLEA.FIELD8
INTO
DB2_TABLEA
FROM
DB1_TABLEA
WHERE
(
((DB1_TABLEA.FIELD4) = 99999)
AND
((DB1_TABLEA.FIELD6)='02' OR (DB1_TABLEA.FIELD6)='22')
)
;
In fact, consider saving the query inside the MS Access database (Ribbon -> Create -> Query Design -> SQL View) and call it as a named object and avoid any long SQL in VBA.
DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute "mySavedQuery", dbFailOnError
Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")
I am using MariaDB and VBA to read/write a flat database using ADODB. This is not by choice however I've been asked to make it work in this manner. An alternative would be to directly use SQL queries however this is a port of a very old VB3 application.
Here is my code that connects to the database, pulls back all records, updates the last record, then calls update to effectively write it back to the database
Global DB As New ADODB.Connection
Global TD As New ADODB.Recordset
DB.Open "Driver={MariaDB ODBC 2.0 Driver};Server=localhost;UID=???;PWD=???;DB=sf_log;Port=3306"
Dim query As String: query = "SELECT * FROM `" & TableName & "` ORDER BY `Record ID`"
TD.CursorLocation = adUseServer
TD.CursorType = adOpenDynamic
TD.Open query, DB, adOpenKeyset, adLockOptimistic
TD.MoveLast
Dim TestColumnField as string
TestColumnField = TD.Fields("TestColumn") 'This returns the correct value from the database indicating the connection was successful
TD.Fields("TestColumn") = "test"
TD.UpdateBatch (adAffectCurrent) ' This line throws the error
Error that is reported is "Query cannot be updated because it contains no searchable columns to use as a key"
The database is a flat relationship-less database with no keys. I have tried setting "record id" to be a primary key with no luck.
Is this error due to MariaDB not implementing/supporting ADODB recorset? Is it due to my database structure? Or is it simply I am utilising the ADODB recorset incorrectly?
Edit: Here is an example that shows you do not need an SQL update statement. You can simply select the data and call Update.
http://www.accessallinone.com/updating-adding-and-deleting-records-in-a-recordset/
Sub ADODBUpdating()
Dim sql As String
Dim rs As adodb.Recordset
sql = "SELECT * FROM tblTeachers WHERE TeacherID=5"
Set rs = New adodb.Recordset
rs.Open sql, CurrentProject.Connection, adOpenDynamic, adLockOptimistic
'Open RecordSet
With rs
If Not .BOF And Not .EOF Then
.MoveLast
If .Supports(adUpdate) Then
![FirstName] = "x" & ![FirstName]
.Update
End If
End If
.Close
End With
Server side cursor implementation seems to be limited, use client side cursors (DB.CursorLocation = adUseClient) instead.
1.) You can't do an update in SQL with a SELECT-Statement. Instead use the UPDATE-Statement.
2.) Dont't try to update all the records. Only Update the single row you want to update. As you write this should be the last record.
You update the testfield and you have to be sufficiently specific in the WHERE-Clause, that you only select the one and only record record you want to update.
how to update null visual basic.net 2012 ,,,
sql="Update mytb set name='' where no_ktp='"& sed.text &"' "
that's cannot
HElp me please . its form my job school
If you wanted to update a tables where a certain value was present, you should use something like the following :
Dim sql = "UPDATE mytb SET name = NULL WHERE no_ktp = #sed"
Use Parameterization, Not Concatenation When Building Queries
You should not be building your database queries like this. It is going to leave you prone to issues with incorrect syntax and possible SQL Injection attacks.
Instead consider adopting an approach like the following that takes advantage of SQL Parameterization and should help avoid issues similar to those previously mentioned :
' Build a Connection to use '
Using connection = New SqlConnection("{your-connection-string}")
' Open your connection '
connection.Open()
' Build your query (using parameters) '
Dim query = "UPDATE mytb SET name = NULL WHERE no_ktp = #sed"
' Build a command to execute '
Using command = New SqlCommand(query, connection)
' Add your parameters '
command.Parameters.AddWithValue("#sed", sed.Text)
' Execute your update '
command.ExecuteNonQuery()
End Using
End Using
I am new to this forum, please could you help me get this code to work, when i execute it, it simply does nothing and does not update the DB. If i remove the square brackets it gives an error: "SYNTAX ERROR in UPDATE statement"
Any help appreciated!
Dim connection As OleDbConnection
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=UserDB.accdb;Jet OLEDB:Database;")
connection.Open()
Dim pass As String
pass = txtconfirm.Text
Dim user As String
user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= '" & pass & "' WHERE [Username]= '" & user & "';"
Dim command As New OleDbCommand(query, connection)
command.ExecuteNonQuery()
connection.Close()
Given your actual connection string, the database that will be updated is the one in the directory where your application starts. This means that if you work with a WinForms application this folder is \BIN\DEBUG or x86 variant. If there is not error then you could get the return value of the ExecuteNonQuery call to verify if a record has been updated or not
Dim rowsUpdated = command.ExecuteNonQuery()
MessageBox.Show("Record updated count = " & rowsUpdated)
If this value is not zero then your database has been updated and you are looking for changes in the wrong database. Check the one in the BIN\DEBUG folder.
In any case your code has big problems. If your variables user or pass contain a single quote, then your code will crash again because your string concatenation will form an invalid SQL. As usual the only workaround is to use a parameterized query
Dim pass = txtconfirm.Text
Dim user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= #p1 WHERE [Username]= #p2"
Using connection = New OleDbConnection("...........")
Using command As New OleDbCommand(query, connection)
connection.Open()
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = pass
command.Parameters.Add("#p2", OleDbType.VarWChar).Value = user
command.ExecuteNonQuery()
End Using
End Using
The parameterized approach has many advantages. Your query text is more readable, there is no misunderstanding between your code and the values expected by your database engine. And while not easy to exploit with MS-Access there is no problem with Sql Injection
I think Steve presents a much better approach for you coding this...
Let me just throw out a few more things:
The reason you can't take those brackets out is some of your column names are reserved words; just FYI.
Since you report "it does nothing..." when you execute, it sounds like you have a valid connection and sql syntax, in which case my next step would be to copy the sql command text while in debug mode, change it to a select and run it in your DB. You should get one result when you do. If not, either your criteria or field contents are not what you think they are...
Just change the Update table SET field-value ... to SELECT * FROM table and leave the WHERE clause as is.