Select from multiple tables without getting Parameter error - sql

I am currently trying to code a database project for a musicians record log. I have been struggling to join 3 tables together in a single search of the database and I am getting this error:
No value given for one or more required parameters.
I have been searching online for why this is but cannot find anything which quite fixes my code. I have tried copying almost word for word other syntax but still get this error. Any help would be much appreciated, my database is as follows:
Program(ProgramID(PK), LengthOfProgram, UserName, NameOfProgram)
ProgramList(PieceListID(PK), PieceID(FK), ProgramID(FK))
Repertoire(PieceID(PK), NameOfPiece, Composer)
Those are the fields needed from repertoire.
Here is my code for when the the program is selected from the list box.
Public dtbConnecter As New OleDbConnection
Dim fileLocator As String = "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source = " + Application.StartupPath + "\Musician Record Log.accdb"
Private Sub lstPro_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstPro.SelectedIndexChanged
Dim programID As String
Dim programIDLength As Integer
Dim selectedString As String = lstPro.GetItemText(lstPro.SelectedItem)
programIDLength = selectedString.IndexOf(":")
programID = selectedString.Substring(0, programIDLength)
MsgBox(programID)
Dim SQL As String = "Select Program.ProgramName, Program.ProgramLength, Repertoire.NameOfPiece, Repertoire.Composer From ((ProgramList INNER JOIN Repertoire ON ProgramList.PieceID = Repertoire.PieceID) INNER JOIN Program ON ProgramList.ProgramID = Program.ProgramID) WHERE (Program.ProgramID = #Param1)"
Dim da As New OleDbDataAdapter
Dim dtbTable As New DataTable
Dim ds As New DataSet
Dim dtbCommand As New OleDbCommand
dtbCommand.Parameters.Add("#Param1", OleDbType.VarChar).Value = programID
dtbCommand.Connection = dtbConnecter
dtbCommand.CommandType = CommandType.Text
dtbCommand.CommandText = SQL
da.SelectCommand = dtbCommand
da.Fill(dtbTable)
'Here i would then use the table's information to update my form, however first i'm trying to get this to work.
da.Dispose()
da = Nothing
End Sub
I also import System.Data, System.Data.OleDb and System.Drawing.Imaging at the top.

It was just a stupid mistake, the names of the fields in the database are NameOfProgram and LengthOfProgram but in the SQL query I used ProgramName and ProgramLength, thanks for all the help in ensuring the SQL query was correct and I did need to correct the data type but the main problem was the wrong identifier.

Related

Why combo box is not loaded from join sql query

Dim cmd As New SqlCommand("SELECT MainDepartmentsTable.ID, FeesTable.ID,FeesTable.Particular,FeesTable.Fee from MainDepartmentsTable inner join SubDepartmentsTable on MainDepartmentsTable.ID = SubDepartmentsTable.MainDeptID inner join FeesTable on SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID WHERE FeesTable.ID = '" & TextDepartmentID.Text & "' ", con)
Dim DataAdopter = New SqlDataAdapter(cmd)
Dim dt As New DataTable
DataAdopter.Fill(dt)
Load_Deparments()
First you need to validate the user input.
Using blocks ensure that you connection and command are closed and disposed.
Parameters save your database from sql injection. I had to guess at the datatype.
Private ConStr As String = "Your connection string"
Private Sub OPCode()
Dim DeptID As Integer
If Not Integer.TryParse(TextDepartmentID.Text, DeptID) Then
MessageBox.Show("Please enter a valid department ID.")
Exit Sub
End If
Dim dt As New DataTable
Using con As New SqlConnection(ConStr),
cmd As New SqlCommand("SELECT MainDepartmentsTable.ID,
FeesTable.ID,
FeesTable.Particular,
FeesTable.Fee
from MainDepartmentsTable
inner join SubDepartmentsTable on
MainDepartmentsTable.ID = SubDepartmentsTable.MainDeptID
inner join FeesTable on
SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID
WHERE FeesTable.ID = #DepartmentID;", con)
cmd.Parameters.Add("#DepartmentID", SqlDbType.Int).Value = DeptID
con.Open()
dt.Load(cmd.ExecuteReader)
End Using
Load_Departments(dt)
End Sub
Private Sub Load_Departments(dt As DataTable)
ComboBox1.DataSource = dt
ComboBox1.DisplayMember = "Particular"
ComboBox1.ValueMember = "Fee"
End Sub
Let's simplify a bit:
Dim sql = "SELECT FeesTable.ID, CoNCAT(FeesTable.Particular, '-', FeesTable.Fee) as DisplayText
FROM
SubDepartmentsTable
inner join FeesTable on SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID
WHERE SubDepartmentsTable.MainDeptID = #id"
Dim da As New SqlDataAdapter(sql, con)
da.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(TextDepartmentID.Text)) 'less worried about AWV with ints but read https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
Dim dt As New DataTable
da.Fill(dt)
'this part connects the data to the combo - it's the part you didn't show in your Q and what people are telling you is missing
yourCombo.DisplayMember = "DisplayText"
yourCombo.ValueMember = "ID"
yourCombo.DataSource = dt
This isn't intended to be a paste in fix for your problem; you've left out too much info from your question to know how to answer it exactly, so you're gonna have to modify this
Things you need to change:
The columns that are selected in the SQL - load one column you will show (I demonstrated how to combine two bits of info under one name of DisplayText) and one column for the backing value (ID)
The column that is filtered on in the where clause or the name of the text box TextDepartmentID - it seems odd to me that a Fee ID should be equal to a Department ID, so I've altered the SQL to retrieve the Fee details for a MainDepartmentID because I've assumed your textbox name is correct and that you intended to show the fees for a department via the subdepartments
Read the blog linked and perhaps choose adding a parameter in a different way
Change yourCombo to the name of your combobox
Change DisplayMember and ValueMember setting to match the names of the two columns your SQL query selects
You only need two columns if youre plumbing up a combo, but if you pass the datatable off somewhere you can add more

How do I change data type to fix data type mismatch in criteria expression

I'm trying to get the database value of an item that i put on a listbox to display to the textbox. (vb.net)
My database table name is 'productlog', in this table has 3 columns, productid, productname, and price. I got the productname to display on a listbox that I made, now I am attempting to display the 3 columns on 3 textboxes. However, I get the "data type mismatch in criteria expression" error on my ExecuteReader line. Here's my code:
Public Class shop
Dim provider As String
Dim datafile As String
Dim connString As String
Dim myConnection As OleDbConnection = New OleDbConnection
Private Sub listboxitems_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listboxitems.SelectedIndexChanged
Dim lbconn As New OleDb.OleDbConnection("PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source = C:\Users\USER PC\Desktop\orderDB1.accdb")
Dim lbcmd As New OleDb.OleDbCommand("SELECT productid, product, price FROM productlog WHERE productid =' & listboxitems.Text & ' AND product ='" & listboxitems.Text & "' AND price =' & listboxitems.Text & '", lbconn)
Dim lbreader As OleDbDataReader
lbconn.Open()
lbreader = lbcmd.ExecuteReader() 'error appearing right here'
While lbreader.Read
txtproductid.Text = lbreader.GetInt32("productid")
txtproduct.Text = lbreader.GetString("product")
txtprice.Text = lbreader.GetInt32("price")
End While
lbconn.Close()
End Sub
Based on the other questions that I looked up, it might be because that 'productid' and 'price' are both integers and what I'm doing is for a String. I tried to remove the double quotes ('"& txtproductid.Text"') and turn them into 'txtproductid.Text', based from another question I looked up. The another answer that I saw was to convert the string into an integer - 'lbcmd.Parameters.AddwithValue("#productid", ConvertInt32("txtproductid.Text"))' not sure if that's correct but I ended up getting the same error. How do I work around this error? Thanks.
UPDATED CODE:
Private Sub listboxitems_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listboxitems.SelectedIndexChanged
Using lbconn As New OleDb.OleDbConnection("PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source = C:\Users\USER PC\Desktop\orderDB1.accdb")
Using lbcmd As New OleDb.OleDbCommand("SELECT productid, product, price FROM productlog WHERE productid = ? AND product = ? AND price = ?", lbconn)
'Set your values here. The parameters must be added in the same order that they
'appear in the sql SELECT command
Dim prodidparam As New OleDbParameter("#productid", Me.txtproductid.Text)
Dim prodparam As New OleDbParameter("#product", Me.txtproduct.Text)
Dim priceparam As New OleDbParameter("#price", Me.txtprice.Text)
lbcmd.Parameters.Add(prodidparam)
lbcmd.Parameters.Add(prodparam)
lbcmd.Parameters.Add(priceparam)
'Open the connection
lbconn.Open()
Using lbreader As OleDbDataReader = lbcmd.ExecuteReader()
While lbreader.Read
txtproductid.Text = lbreader.GetInt32("productid").ToString()
txtproduct.Text = lbreader.GetString("product")
txtprice.Text = lbreader.GetInt32("price").ToString()
End While
End Using
End Using
End Using
End Sub
You should not use string concatenation to create your SQL query as you are doing here. That opens you up to a sql injection hack. Instead you should use a parameterized query.
Try something like this (not tested):
Using lbconn As New OleDb.OleDbConnection("PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source = C:\Users\USER PC\Desktop\orderDB1.accdb")
Using lbcmd As New OleDb.OleDbCommand("SELECT productid, product, price FROM productlog WHERE productid = ? AND product = ? AND price = ?", lbconn)
'Set your values here. The parameters must be added in the same order that they
'appear in the sql SELECT command
lbcmd.Parameters.Add("productid", OleDb.OleDbType.Integer).Value = 1234
lbcmd.Parameters.Add("product", OleDb.OleDbType.VarChar).Value = "value of product"
lbcmd.Parameters.Add("price", OleDb.OleDbType.Integer).Value = 999
'Open the connection
lbconn.Open()
Using lbreader As OleDbDataReader = lbcmd.ExecuteReader()
While lbreader.Read
txtproductid.Text = lbreader.GetInt32("productid").ToString()
txtproduct.Text = lbreader.GetString("product")
txtprice.Text = lbreader.GetInt32("price").ToString()
End While
End Using
End Using
End Using
Since your code is using OleDbConnection you can't use named parameters. Note the question marks in the SELECT statement which server as placeholders for the values.
Note that when using OleDb, you have to add the parameters in the same order as they appear in your sql query.
The Using ... End Using statements ensure that the connection, command and datareader are disposed properly.

How to get linked table details in dataview?

I have two linked tables like this
Here myDataset.cat_table is already filled at form load,used for other purpose, and me getting data from myDataset.prod_table bydataview by the below script.
Dim myDataView As New DataView
myDataView.Table = Me.myDataSet.prod_table
For Each myRow As DataRow In myDataView.ToTable.Rows
Dim myId as integer
Dim myCatid as integer
Dim myCatName as object
Dim myprodDetails as object
myId = myRow("id")
myCatid = myRow("catid")
myCatName = ?
myprodDetails = myRow("details")
Next
Here in Dataview method, is it possible to get "myCatName" from the linked table? Me not looking for a separate query (by left join), because again i have to load query. And "Merge table" works for identical tables only i guess, So searching for other possible logics
Yours faithfully
Murulimadhav
Hopefully, these two tables are not just data sets but if they can possibly be real database tables from sql, my suggestion is that you can easily manipulate the data of linked tables by SQL query. P.S - Import the following references.
Imports System.Data.SqlClient
Private strConn As String
Private sqlConn As New SqlConnection
Private sqlcmd As New SqlCommand
Private Sub getdatatable()
strConn = "Data Source= Server_Name;Initial Catalog= DB_Name;User ID= User_name;Password= Password"
sqlConn = New SqlConnection(strConn)
sqlConn.Open()
Dim sqlcmd As New SqlCommand("SELECT p.id, c.catname, p.products, p.details FROM cat_table c, prod_table p WHERE c.catid = p.catid", sqlConn)
Dim myreader As SqlDataReader
myreader = sqlcmd.ExecuteReader
myreader.Read()
Do While myreader.HasRows
'datagridview.Rows.Add(myreader.Item("id").ToString, myreader.Item("catname").ToString, . . . and so on as your desire table columns that you want to show on datagridview)
Do While myreader.Read
'datagridview.Rows.Add(myreader.Item("id").ToString, myreader.Item("catname").ToString, . . . same coding as above Do while looping)
Loop
myreader.NextResult()
Loop
End Sub
Trigger this method on Form_load or button click or whatever as you like. Before you do this type of showing in datagridview, you must pre-define the respective columns first in datagridview. I hope I will help you a little bit.
Dim myDataView As New DataView
myDataView.Table = Me.myDataSet.prod_table
For Each myRow As DataRow In myDataView.ToTable.Rows
Dim myId As Integer
Dim myCatid As Integer
Dim myCatName As Object
Dim myprodDetails As Object
myId = myRow("id")
myCatid = myRow("catid")
Dim myCatPosi As Integer = cat_tableBindingSource.Find("id", myCatid)
If myCatPosi >= 0 Then
cat_tableBindingSourceBindingSource.Position = myCatPosi
myCatName = cat_tableBindingSourceBindingSource.Current("title").ToString
End If
myprodDetails = myRow("details")
Next

Trying to delete a record from my access database in visual basic studio 2010

Private Function CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection) As OleDbDataAdapter
// Initiating instances for the function
Dim dataAdapter As OleDbDataAdapter = New OleDbDataAdapter()
Dim myCommand As OleDbCommand
Dim parameter As OleDbParameter
// establishing the string to tell where to delete record from and how to find the record i want.
// PlayerIDTextBox.Text is a text on a form that is populated from the database after selecting a list of name (this works correctly) // connection is already open and is directed to correct place
Dim sql As String = "DELETE * FROM Players WHERE ID ='" & CInt(PlayerIDTextBox.Text) & "'"
myCommand = New OleDbCommand(sql, playerDBconnection)
parameter = myCommand.Parameters.Add("ID", OleDbType.Char, 3, "ID")
parameter.SourceVersion = DataRowVersion.Original
dataAdapter.DeleteCommand = myCommand
Return dataAdapter
End Function
// i call this function after executing a button click.
//ListPlayerComboBox.Text is populated with the names and needs it a name to fill PlayerIDTextBox.Text(works correctly)
Private Sub RemovePlayerButton_Click(sender As System.Object, e As System.EventArgs) Handles RemovePlayerButton.Click
If ListPlayerComboBox.Text = " " Then
MsgBox("Please Select a Player.")
Else
Me.CreatePlayerAdapter(playerDBConnection)
End If
End Sub
// no errors occur. However, nothing is done in the database. help please?
Notes:
1)Never leave your OleDbConnection Open. Only allow it to be opened when you actually need it. This will save you from a lot of headaches later on. The reasons why can be found on following stackoverflow question.
2) There is no reason to return an OleDbDataAdapter if you don't intend on using it.
3) Use your parameters correctly : see below example2
4) Keep in mind that there are some restricted keywords in Access. Luckely for you ID isn't one. The restrictedKeywords can be found here: Keywords
I'm probably missing some further points here. Anyone should be free to add em.
Why not adjust your Function CreatePlayerAdapter to the following:
1) Without parameters
Private Sub CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection)
Dim myCommand As OleDbCommand
Dim sql As String = "DELETE * FROM Players WHERE ID =" & CInt(PlayerIDTextBox.Text)
myCommand = New OleDbCommand(sql, playerDBconnection)
playerDBconnection.Open()
myCommand.ExecuteNonQuery()
playerDBconnection.Close()
End Sub
2) With parameters
Private Sub CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection)
Dim myCommand As OleDbCommand
Dim sql As String = "DELETE * FROM Players WHERE ID = #playerId"
myCommand = New OleDbCommand(sql, playerDBconnection)
Dim param As New OleDb.OleDbParameter(#playerId", CInt(PlayerIDTextBox.Text))
myCommand.Add(param)
playerDBconnection.Open()
myCommand.ExecuteNonQuery()
playerDBconnection.Close()
End Sub
The method ExecuteNonQuery executes the query passed to the command on the specified OleDbConnection and returns the number of rows affected. More info Here

How to update a MS Access database in vb.net

Hi I'm having trouble with updating one of my tables using vb.net when i click on the button to update the data base it give me the error "System.Data.OleDb.OleDbException: No value given for one or more required parameters."
here is the code
Protected Sub Button6_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button6.Click
Dim aConnection As New OleDbConnection
Dim aCommand As New OleDbCommand
Dim SQLQuery, aConnectionString As String
Dim Text As String = TextBox1.Text
Dim aDataAdapter As New OleDbDataAdapter
Dim aDataReader As New DataSet
SQLQuery = "Update Review Set report='Yes' Where Text='" & Text & "'"
aConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Server.MapPath("App_Data/BookReviewWebsite.accdb")
aConnection = New OleDbConnection(aConnectionString)
aConnection.Open()
aCommand = New OleDbCommand(SQLQuery, aConnection)
aCommand.ExecuteNonQuery()
Label15.Text = "Review has been reported"
aConnection.Close()
End Sub
Review, Report and Text. Here you have two fields and a table name, you should check if your database effectively contains a table named Review and if, in this table, there are two field named report and Text.
If your really have this table and these fields, then you need to enclose the word TEXT with square brackets because the word TEXT is a reserved keyword in Access 2007.
Last, but not least of your problems is the query string itself. Concatenating strings in that way could be a source of errors. If you have a single quote in your 'Text' variable then the results could be impredictable and range from Syntax error to Sql Injection
SQLQuery = "Update Review Set report='Yes' Where [Text]=?"
aCommand = New OleDbCommand(SQLQuery, aConnection)
aCommand.Parameter.AddWithValue("#p1", Text)
aCommand.ExecuteNonQuery()