Query Access Visual Basic - sql

I am trying to figure out how to query an access db using visual basic but I'm looking for a little explanation on how this actually works.
What I'm confused about is that I state a command SELECT * FROM PI (PI Being the table) but then directly below that, I'm saying that TextBox1.Text = theDataTable.Rows(0).Item(1).
I'm just wondering why I have a query command and then a seperate command that is going to a specified Row and Item....any help is much appreciated!
Imports System.Data.OleDb
Public Class Form1
Dim theConnectionString As New OleDbConnection
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
txtSQL.Clear()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
theConnectionString.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Marc Wilson\Documents\FiddleFuckDB.accdb"
theConnectionString.Open()
Dim theDataSet As New DataSet
Dim theDataTable As New DataTable
theDataSet.Tables.Add(theDataTable)
Dim theDataAdapter As New OleDbDataAdapter
theDataAdapter = New OleDbDataAdapter("SELECT * FROM PI", theConnectionString)
theDataAdapter.Fill(theDataTable)
TextBox1.Text = theDataTable.Rows(0).Item(1)
theConnectionString.Close()
End Sub
End Class

Like this
"SELECT * FROM PI Where FieldName = '" & TextBox1.Text & "'"
assumed that your field type is not numeric

Since you're using an ADO.NET DataTable - that object consist of Rows collection and each row in turn consists of Items collection. So in order to get to a specific value you need to use
Table.Rows(X)(Y)
notation. Even if your query returns a single value - you would use this approach. Looking at your code and Items(1) especially, it looks like your query returns at least 2 columns.
If you're interested in a single value only, consider specifying a single column name in your query, make sure that it returns a single row (e.g. by adding WHERE clause to your query) and use ExecuteScalar ADO.NET command, which, unlike Fill and DataTable returns a single value only.

Not 100% sure I undertand the question, but hopefully this helps:
The query command is fetching all of the records from the table in your database. The Rows() and Item() methods fetch a particular field from a particular record (in this case, the second field of the first record).
The Text property of your TextBox cannot display the entire table on it's own: the DataTable is a fairly complicated data strucutre. TextBoxes require a string (or something like one).

SELECT * FROM PI tells the database engine which data it should retrieve from the underlying database table that exists on-disk.
You're using the DataTable class which represents data in-memory: the DataAdapter class reads data from disk (using the SQL statement) and copies it into memory, where you then use the Rows(0).Item(1) command to get a copy of the data already in memory.
The alternative is to use DataReader which is more direct, often simpler. In your case I don't see why you're using the DataTable class because DataReader will suit you fine.

Related

How to edit a record in an access database - visual basic

I want to edit a specific record in an access database but I keep on getting errors
this is the database I want to edit:
Access database
these are flashcards that the user has created and stored in an access database. What I want is that the user is able to edit the difficulty so it appears more/less often
This is the module:
Module Module1
Public Function runSQL(ByVal query As String) As DataTable
Dim connection As New OleDb.OleDbConnection("provider=microsoft.ACE.OLEDB.12.0;Data Source=flashcard login.accdb") 'Establishes connection to database
Dim dt As New DataTable 'Stores database in table called dt
Dim dataadapter As OleDb.OleDbDataAdapter
connection.Open() 'Opens connection
dataadapter = New OleDb.OleDbDataAdapter(query, connection)
dt.Clear() 'Clears datatable
dataadapter.Fill(dt) 'Fills datatable
connection.Close()
Return dt
End Function
End Module
And here is the button that the user can press to edit the database:
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = '" & TxtDifficulty.Text
runSQL(sql)
End Sub
The difficulty column in the database should be able to be edited by the user through the value they entered in txtDifficulty.text
Good to hear I found the problem with the apostrophe.
I am going to need a where statement but the problem I have is that the user can create as much flashcards as they want so how would I write the where statement?
An INSERT statement does not have a WHERE clause but an UPDATE does and is usually by a primary key.
Look at how I add a new record ignoring mHasException and specifically using parameters. In this case a List is used but with little effort an array of DataRow can be passed instead.
Here is an example for updating a record with a DataRow.
To get other code samples for ms-access see the following repository.
In closing, in the above repository I don't get into all possibilities yet there should be enough there to get you going. And when reviewing code I flip between Add for adding a parameter and AddWithValue while Add is the recommend way but both are shown to see differences. see also Add vs AddWithValue.

How to edit a specific entity inside an access database

I made an access database which stores all the flashcards that the user has created.
Here it is:
When the user creates a flashcard, the difficulty is set to 3 and the user is able to change the difficulty through txtDifficulty
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = " & TxtDifficulty.Text 'Changes difficulty to user input
runSQL(sql) 'runs SQL
End Sub
The problem with the above code is that it edits every single flashcard inside the database rather than just the individual flashcard.
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = " & TxtDifficulty.Text 'Changes difficulty to user input
sql = sql & "WHERE Front = " & txtFront.Text
runSQL(sql) 'runs SQL
End Sub
I edited the code to the above which I thought that it will only edit where Front in the database is equal to txtfront.text which is the textbox where the flashcard appears to the user but this just produces an error.
I was wondering how to only edit the specific flashcard that the user is on. Im guessing it might be something to do with the unique identifier in the access database but im not sure how to implement it
Your idea to "only edit where Front in the database is equal to txtfront.text" is a good one, but concatenating values into an SQL query is fraught with potential problems.
If you pass the values to the query as SQL parameters then you don't need to worry about putting quotes around values, which is one of the problems for the code in the question.
You can write the SQL query over more than one line to make it easier to read: extra whitespace in the query is OK, but no whitespace (another of the problems for the code in the question) is a problem, usually a syntax error.
If you keep the database operation in a separate method, it keeps each part of the code in its own method, which makes it easier to be sure that each part is doing what it should and also easier to maintain.
Sub UpdateDifficultyLevel(front As String, difficulty As Integer)
Dim sql = "UPDATE flashcards SET difficulty = ?
WHERE Front = ?"
Using conn As New OleDbConnection("yourConnectionStringHere"),
cmd As New OleDbCommand(sql, conn)
cmd.Parameters.Add("#difficulty", OleDbType.Integer).Value = difficulty
cmd.Parameters.Add("#front", OleDbType.VarWChar).Value = front
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim difficulty As Integer
If Integer.TryParse(TxtDifficulty.Text, difficulty) Then
Dim front = txtFront.Text
UpdateDifficultyLevel(front, difficulty)
Else
' tell user that the difficulty must be a number
End If
End Sub
The parameters are represented by question marks in the query, and you have to add the parameters in the same order as they are used. Giving a name to each parameter ("#front", etc.) is just to make it easier to see which one is which (the name would actually be used if another database, such as SQL Server, was used).
The Using statement makes sure that any "unmanaged resources" are released after they've been used.
You might also need to use the UserID in the update query, but I could not gauge that from the question.

Data retrieval from Access file into DataTable not working

I have some code to connect a database with the program, but for some reason at run time it does not show the data from the DB.
Public Class Form2
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\employee\employee.accdb")
Dim cmd As New OleDbCommand("", con)
Dim empDA As New OleDbDataAdapter
Dim empTable As New DataTable
Dim dr As OleDbDataReader
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.EmpTableAdapter.Fill(Me.EmpDataSet.emp)
Dim cmd As New OleDbCommand("select * from emp", con)
empDA = New OleDbDataAdapter("select * from emp", con)
empDA.Fill(empTable)
DataGridView1.DataSource = empDA
End Sub
The code in the question looks to be a bit muddled as to what needs to be done.
Variables should be limited to the minimum scope that they are needed in, and some things need to be disposed of after use (to avoid memory leaks, files remaining locked, and other problems with computer resources).
For the disposal, the Using statement is useful as it makes sure that that is done automatically.
You should try to put each logical piece of code in a suitably small method so that it is easier to work with. Perhaps something like this:
Imports System.Data.OleDb
Public Class Form2
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\employee.accdb"
Sub ShowEmployeeData()
Dim sql = "SELECT [Id], [FirstName] FROM [Employees] ORDER BY [Id]"
Using conn As New OleDbConnection(connStr)
Using cmd As New OleDbCommand(sql, conn)
Dim employees As New DataTable()
Dim da As New OleDbDataAdapter(cmd)
da.Fill(employees)
DataGridView1.DataSource = employees
End Using
End Using
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ShowEmployeeData()
End Sub
End Class
So the connStr variable is available everywhere in the class Form2, and the code that shows the employee data is in its own Sub.
When querying a database, you should specify the actual columns that you need, so that the columns are returned in the order you want, and order by one of the columns so that the data is returned in a predicatable order - databases are free to give you any order for anything if you don't tell them otherwise.
Ok, while you have some tips and suggestions, I'll give a few more.
First, try using the project setting to create the connection. The reason for this is not only can you create + test + make a connection, you can do this without code.
so, try this to build + create the connection:
so now click on the [...] and it will launch the connection builder for you!
So you now get this:
(use the change button if it defaulted to sql server).
So, using the above allows you to build ONE connection - one that you can use for the WHOLE application.
And there is the handy test connection button!!
So, in above we called the connection "MyDB".
That way we don't have messy connection strings in code, and we have ONE place to change/set the connection.
Now, in code?
Well, as a really nice tip?
You often need a connection
You often need a data reader.
and you need some sql (command text).
So, in place of declaring that reader, declaring the conneciton, and all that jazz?
use a command object!
Why?
because the command object has ALL of the above 3 objects in one nice simple ONE object.
As a result, you don't have to declare the 3 separate objects.
Just use and adopt a command object in MOST cases.
So, now our code has this:
Imports System.Data.OleDb
Public Class DataGridTest1
Private Sub DataGridTest1_Load(sender As Object, e As EventArgs) Handles Me.Load
Using cmdSQL As New OleDbCommand("SELECT ID, FirstName, LastName, HotelName from tblHotels",
New OleDbConnection(My.Settings.MyDB))
cmdSQL.Connection.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
DataGridView1.DataSource = rstData
End Using
End Sub
End Class
Note how simple - and how few variables we have to setup and declare.
So, I find this becomes quite much as easy as using Access or even writing older VB6 code.
So, try the above - its very little code, and use the connection builder in the "settings" for the application - thus removing the need to introduce connection strings all over the place in code.

Delete record from Access database vb.net

In this project I use Access database which is displayed in DataGridView. I am trying to delete acces row but i my looking for was not successful.
Code to delete record from DataGridView:
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim index As Integer
index = DataGridView1.CurrentCell.RowIndex
DataGridView1.Rows.RemoveAt(index)
ZoznamBindingSource.RemoveCurrent().
‘Dim da As OledbDataAdapter
‘Dim ds As dataSet
da.Update(ds)
End Sub
The last line of code give me an error: SystemNullReferenceException. I know rhe dataset is problem but i don’t know which code will replace it with.
Any solution?
The whole point of a BindingSource is that it is the one and only point of contact for bound data. You shouldn't have to touch the UI and you shouldn't have to touch the data source.
In your case, you should be calling RemoveCurrent on the BindingSource. That will flag the underlying DataRow as Deleted and then, when you call Update on your data adapter, the corresponding database record will be deleted.

I am trying to alphabetize a combo box using a query in my vb code. How do i get it to work Im having problems?

I want to know if its possible to somehow use a query in my vb code to alphabetize a list in a combo box that I have a dataset connected to?
Here is my code:
Private Sub ValueSourceAvailabilityBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) Handles ValueSourceAvailabilityBindingNavigatorSaveItem.Click
Me.Validate()
Me.ValueSourceAvailabilityBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.ValueTrackerDataSet)
End Sub
Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'ValueTrackerDataSet3.SA_CountryCode' table. You can move, or remove it, as needed.
Me.SA_CountryCodeTableAdapter.Fill(Me.ValueTrackerDataSet3.SA_CountryCode)
'TODO: This line of code loads data into the 'ValueTrackerDataSet2.SA_Client' table. You can move, or remove it, as needed.
Me.SA_ClientTableAdapter.Fill(Me.ValueTrackerDataSet2.SA_Client)
'TODO: This line of code loads data into the 'ValueTrackerDataSet1.Cubes' table. You can move, or remove it, as needed.
Me.CubesTableAdapter.Fill(Me.ValueTrackerDataSet1.Cubes)
'TODO: This line of code loads data into the 'ValueTrackerDataSet.ValueSourceAvailability' table. You can move, or remove it, as needed.
Me.ValueSourceAvailabilityTableAdapter.Fill(Me.ValueTrackerDataSet.ValueSourceAvailability)
End Sub
Private Sub ClientIDComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ClientIDComboBox.SelectedIndexChanged
SELECT *
FROM dbo.SA_Client
ORDER by ClientName
End Sub
End Class
You can't just put a SQL statement inside of a VB .Net sub like that. You need to either use LINQ/Entity Framework, or format the query as a string and send it to SQL. The first method would depend on how your entity is set up, while the second method would look something like this:
'The SQL Connection
Dim sqlLConn As New SqlConnection()
'The SQL Command
Dim sqlCmd As New SqlCommand()
'Set the Connection String
sqlConn.ConnectionString = "connection string goes here"
'Open the connection
sqlConn.Open
'Set the Connection to use with the SQL Command
sqlCmd.Connection = SQLConn
' Set your query
sqlCmd.CommandText = "SELECT * FROM dbo.SA_Client ORDER by ClientName"
' DO STUFF WITH THE sqlCmd query here...
'Close the connection
sqlConn.Close()
First option: You can do it programatically by your sql Query
SELECT * FROM tableName ORDER BY columnName ASC/DESC
second option by settiong the Sorted option to TRUE
Would it solve your problem if the data you retrieved from the database already had the data sorted in ClientName order? In that case, you'll need to change the SQL associated with the Fill method on your SA_ClientTableAdapter data adapter.
If you need to sort the data separately from the DataSet and DataTable, you have a couple of options.
You can use LINQ, and bind to a sorted version of your data. Rather than binding directly to the DataSet or DataTable, you'd bind to an expression:
[whatever you're binding] = Me.ValueTrackerDataSet2.SA_Client.OrderBy(c=>c.ClientName)
You can use a DataView over the DataTable, which is (one of) the older ways we used to do this:
Dim dv as DataView = New DataView(Me.ValueTrackerDataSet2.SA_Client, "", "ClientName", DataViewRowState.CurrentRows)
[whatever you're binding] = dv