Inserting Records into a database - sql

Whenever i run the code and try to run the SQL query it says Datatype mismatch
The code is as follows:
Public Class Form7
Public insert As New DBController
Public username, password, ID As String
Public chars(20) As Char
Public cc As Integer
Private Sub BTNSaveRecord_Click(sender As Object, e As EventArgs) Handles BTNSaveRecord.Click
chars = TXTLastName.Text.ToCharArray
ID = chars(0) & chars(1) & chars(2)
insert.AddParameters("#ID", ID)
insert.MakeQuery("SELECT Driver_ID FROM Driver WHERE Driver_ID LIKE '%#ID%'")
ID = ID & (insert.recordcount + 120).ToString
insert.clearDT()
cc = Conversion.Val(TXTCarCapacity.Text)
MsgBox(cc)
insert.AddParameters("#ID", ID)
insert.AddParameters("#Fname", TXTFirstName.Text)
insert.AddParameters("#Lname", TXTLastName.Text)
insert.AddParameters("#CarCap", cc)
insert.AddParameters("#pass", "Password1")
username = TXTFirstName.Text & TXTLastName.Text.First
MsgBox(username)
MsgBox(ID)
insert.AddParameters("#user", username)
insert.MakeQuery("INSERT INTO Driver (Driver_ID,Maximum_Case_Capacity,Driver_Username,Driver_Password,Driver_FirstName,Driver_LastName) " &
"VALUES (#ID,#CarCap,#user,#pass,#Fname,#Lname);")
End Sub
If you want to know the code for the DB controller i have the code. That is a self defined class to make the SQL stuff less repetitive. Like the data adapters command builders and datatables.
This is the table in the database I am inserting a new record in. This has no relationships too it that will stop me from entering a new record. The image contains the datatype types of each field
Details for maximum_case_capacity

Access does not care what you call your parameters; the names are ignored. It is the order the parameters are added that matches them to the database. Since the order of the fields do not match the order the parameters are added you are getting a type mismatch when Access tries to add the string FName to the numeric field Maximum_Case_Capacity.
insert.AddParameters("#ID", ID)
insert.AddParameters("#CarCap", cc)
username = TXTFirstName.Text & TXTLastName.Text.First
insert.AddParameters("#user", username)
insert.AddParameters("#pass", "Password1")
insert.AddParameters("#Fname", TXTFirstName.Text)
insert.AddParameters("#Lname", TXTLastName.Text)
In a real application, you would never add passwords as plain text. Also, the interesting dance you do to get a unique primary key (maybe) could be avoided if you used a numeric autoincrement field in Access. I am afraid you will run out of space in that field rather quickly as it is only 6 characters wide. Hope you don't get too many people named Smith. ;-)

Related

Chinese characters in Access SQL Query

After populating the recordsource the next action is clicking on one of the fields populated to "activate" the record. When clicking this, the goal is that the SEC_ID (A GUID, Number Data Type) is stored as a tempvar and used in future queries. This GUID is also placed in a text box just for a visual debug. However it doesn't put the GUID, it puts random Chinese characters. I've tried to place it into a MsgBox just to also see and it spits out "???????".
My code to populate the rowsource:
Dim componentListSQL As String
If FCSUtilities.AssessmentUoM = "Metric" Then
componentListSQL = "SELECT DISTINCT [100b_Working].SEC_SYS_COMP_ID, [100b_Working].SEC_ID, [110b_RO_Material_Category].MAT_CAT_DESC, [110b_RO_Component_Type].COMP_TYPE_DESC, [110b_RO_Material_Category].MAT_CAT_ID, [110b_RO_Component_Type].COMP_TYPE_ID, [100b_Working].ID_Number, [100b_Working].Model, [100b_Working].Serial_Number, [100b_Working].Capacity, [100b_Working].Manufacturer, [100b_Working].SEC_YEAR_BUILT, ROUND([100b_Working].SEC_QTY, 0) AS SEC_QTY, [100b_Working].UOM_MET_UNIT_ABBR, [100b_Working].UOM_ENG_UNIT_ABBR, [100b_Working].Equipment_Make, [100b_Working].UOM_CONV " _
& "FROM (110b_RO_Units_Conversion INNER JOIN (110b_RO_Component_Type INNER JOIN (110b_RO_Material_Category INNER JOIN 110b_RO_CMC ON [110b_RO_Material_Category].MAT_CAT_ID = [110b_RO_CMC].CMC_MCAT_LINK) ON [110b_RO_Component_Type].COMP_TYPE_ID = [110b_RO_CMC].CMC_CTYPE_LINK) ON [110b_RO_Units_Conversion].UOM_ID = [110b_RO_CMC].CMC_UoM) INNER JOIN 100b_Working ON [110b_RO_CMC].CMC_ID = [100b_Working].SEC_CMC_LINK " _
& "WHERE ((([100b_Working].SEC_SYS_COMP_ID) = [Forms]![200a_MainWindow]![txtDebugCompSysID]) And (([100b_Working].SEC_ID) Is Not Null)) " _
& "ORDER BY [110b_RO_Component_Type].COMP_TYPE_DESC;"
Me![210_ComponentList].Form.RecordSource = componentListSQL
End If
The OnClick event:
Private Sub txtMaterialCategory_Click()
Me.txtActiveSecID.Value = Me.txtSecID.Value
End Sub
The txtSecID appears as a GUID as it should but it's in the txtActiveSecID that it becomes Chinese characters even if I attempt to put it as a tempvar then set it into the txtActiveSecID.
I'm not exactly sure what is going on. Looking at different stacks, it points that it's due to long/memo field but as I said previously, the SEC_ID field data type is Number.
Per MS documentation https://learn.microsoft.com/en-us/office/vba/api/Access.Application.StringFromGUID:
The Microsoft Access database engine stores GUIDs as arrays of type Byte. However, Access can't return Byte data from a control on a form or report. To return the value of a GUID from a control, you must convert it to a string. To convert a GUID to a string, use the StringFromGUID function. To convert a string back to a GUID, use the GUIDFromString function.
StringFromGUID(Me.txtSecID.Value)
However that results in output like:
{guid {2786C27B-CB7C-4DEA-8340-1338532742DE}}
That should still work as filter critera but could do further processing to extract GUID from that string. Use string manipulation functions to remove the {guid header and trailing }. Review Access - GUID value stored in textbox, can't be used in SELECT statements

Find data location based on Primarykey ID

I am very new to access and vba so apologies in advance for glaring conceptual gaps.
Basically I have a button that, when clicked, prompts a user to enter an ID number. The ID entered will correspond to one of my primary keys in a specific table (I have some checks in place to make sure the entered ID is valid).
I need my code to identify the row number of the ID entered and be able to populate a specific column in that row. I know Access does not refer to data locations using rows/cols but that is the best way I thought to describe it.
I am using Index/Seek/NoMatch to make sure the entered ID number is valid and I have been trying to find a way to also use those functions to generate the data location but have not had any luck. Any help would be greatly appreciated.
I think DLookup() function will work for your case. Suppose you have following dataset in table tblEmpInfo where EmpID is primary key field.
If you want to return employee name by entering employee id in a inputbox then use DLookup() like below-
Private Sub cmdDataLookup_Click()
Dim strEmpName As String, InputID As String
InputID = InputBox("Enter employee ID:", "Input ID")
strEmpName = DLookup("EmpName", "tblEmpInfo", "EmpID= '" & InputID & "'")
MsgBox strEmpName
End Sub
If you want to update any name by entering EmpID then use UPDATE SQL statement. Try below.
Private Sub cmdUpdateInfo_Click()
Dim strSQL As String, InputID As String
InputID = InputBox("Enter employee ID:", "Input ID")
strSQL = "UPDATE tblEmpInfo Set EmpName= 'Updated Value' WHERE EmpID= '" & InputID & "'"
CurrentDb.Execute strSQL
End Sub
Note: There is no direct way to get row number and column number of a Field in access but you can apply some trick by VBA to get row and column number of a Field. I will suggest to ask a separate question to get that.

Unable to insert string into Access database

I am using a WPF application to insert a student into my MS Access database.
I wanted to use a parameter with this code:
Dim sql As String = _
"INSERT INTO exams " & _
"VALUES (#student)"
Dim opdracht As OleDbCommand = New OleDbCommand(sql, connectie)
opdracht.Parameters.Add(New OleDbParameter("#student", 5))
but this doesn't work.
The only way i get it to work is this one:
Dim sql As String = _
"INSERT INTO exams " & _
"VALUES (" & student & ")"
' opdracht initialiseren
Dim opdracht As OleDbCommand = New OleDbCommand(sql, connectie)
To use this query I use the command, this is the point where I get my error.
opdracht.executeNonQuerry()
The table layout in MS Access looks like this:
And my application inserts the other values corectly but i left them out to keep a minimal example.
If you have a variable named student and you want to use its value for the parameter then you need to assign that variable as parameter's value
Dim sql As String = "INSERT INTO exams VALUES (#student)"
Dim opdracht As OleDbCommand = New OleDbCommand(sql, connectie)
opdracht.Parameters.AddWithValue("#student", student)
opdracht.ExecuteNonQuery()
Of course, I am assuming this because you say that the string concatenation version is working, and in that example you concatenate the value of a variable named student in your command text
Remember that with OleDb the name of your parameters is meaningless because OleDb use the position of the placeholder to pass the parameters' values, not the parameter name
EDIT Using INSERT INTO without specifying the column names works only if you add the parameters for all fields. Your database table contains other fields so you need to specify them or use a different syntax for the INSERT INTO
Dim sql As String = "INSERT INTO exams (Student) VALUES (#student)"
But this will fail also because you have the Student field part of your primary key. The fields that belong to a Primary Key cannot be null so you have no choice but add all the values required by the primary key
Dim sql As String = "INSERT INTO exams (Student, locaal, opleidingsOnderdeel) " & _
"VALUES (#student, #local, #oplei)"
.. add the parameter's value for student, local and oplei
However, I am a bit perplexed that the string concatenation works. What is the value of the variable student? You should get the same error as using the parameterized query with only one parameter.

InvalidCastException in Linq to entities query

I am making an application for my department at work. I have run into a big problem.
I am trying to get the primary key of a name selected on a ListBox control. This ListBox control is populated from a query from the database when the form loads. Below is the query used to populate the ListBox control.
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select officer.First_Name.ToUpper & " " & officer.Last_Name.ToUpper
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
The query works fine and the ListBox is populated as expected. The problem is I am trying to get the value of the primary key of the selected ListBox item. The primary key value I am trying to retrieve is an integer value and it is set as an identity.
Below is a summary of my database.
Table Exam_Officer:
Officer_ID as int which is the primary key and is also set as an identity column
First_Name as nvarchar
last_Name as nvarchar
One other Table is Result_Submitted,
its columns are:
sn as integer primary key and an identity column
Officer_ID as an int and is a foreign key to the Table Exam_Officer
Result_Submitted as nvarchar
Outstanding_Result as nvarchar
This is the code I am trying to use to get the officer_ID from the SelectedItem property of the ListBox control of a Windows form.
Dim selectedOfficer As Exams_Officer = DirectCast(lstFullname.SelectedItem, Exams_Officer)
Dim selectedOfficerID As Integer = selectedOfficer.Officer_ID
The code dosen't work it throws an error on the first line (directcast method)
System.InvalidCastException was unhandled
Message=Unable to cast object of type 'System.String' to type 'EXAMINATION_OFFICER_PAYMENT.Exams_Officer'.
Source=EXAMINATION OFFICER PAYMENT
I am confused and don't know what else to do. Any help is appreciated.
To be honest, I'm surprised it's even displaying at the moment as FullName isn't a property of String. Look at your code:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select officer.First_Name.ToUpper & " " & officer.Last_Name.ToUpper
You're selecting the full name - so the result of your code is just the names, not the original officers. I suspect you want:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
At that point, you've got a list of officers rather than a list of strings. This is assuming FullName is a property of your officer type though. If it's not, you might want to project to a list where you do the string concatenation in one property, but keep the original officer in another property. For example:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select New With {
.FullName = officer.First_Name.ToUpper & " " _ & officer.Last_Name.ToUpper,
.Officer = officer
}
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
Then later, you'd need to extract the value of the Officer property to get at the officer object itself.
In general the way to do this is to add Officers to your ListBox and override Officer's ToString() method to return FullName, or bind and set DisplayMember to Fullname. Like Jon Skeet, I'm not sure why the code you've posted is working...
Then you can do
Dim selectedOfficer As Exams_Officer = DirectCast(lstFullname.SelectedItem, Exams_Officer)
and Exams_Officer.OfficeID will be okay.
At the moment you are casting a string to an Officer, the above casts an Object to an Officer, which is more likely to work.
Bear in mind however that you need to instance all your officers and that they'll be in memory. So if had a lot of and/or Officer was a hefty object, performance might start to suffer.
The simplest option at that point is a small class / structure with just ID and name in it.

MS access SELECT INTO in vba

I'm having some issues with some functionality of my application. There is a particular instance where I have an instance of a 'pending class' on a form for an administrator to review. The form is populated with students associated with this pending class. After their grades are finished, I have a button at the footer that will delete this class from my 'pending' table and add the grades to all of the students. This works.
However, I want to essentially copy this pending class, which just has the class name, date, and teacher to a completed class table before it's deleted from pending. Since no data about this class other than the primary key(class number) persists throughout this form, I can't populate the other fields(class name, date) of the row into my completed class table.
I am trying a "SELECT INTO" operation in VBA to get these values. It's going like this:
dim cname as String
dim classdate as Date
dim pid as integer
dim teacher as String
dim qry as String
pid = [Forms]![frmClasses]![txtID]
qry = "Select className INTO cname FROM tblPending WHERE tblPending.id = " & " ' " & pid & " ' " & ";"
db.execute qry
debug.print qry
debug.print cname
From here, I do the same operations for each other variable, build my INSERT query, and execute it. The problem is-- my select into's are not working. Debug.print shows that the local variables were never initialized from the SELECT INTO statement. Any thoughts?
First, having all classes in one table and just setting a "NotPending" or "Completed" column would be better.
Having two identical tables for classes and moving values from one into the other to indicate status changes is bad database design.
If you really need to do this by using two tables and copying rows, then you need an INSERT INTO query (and not SELECT INTO), as already mentioned by Remou in the comments, because SELECT INTO creates a new table (or overwrites an existing one with the same name, if already there).
The syntax for INSERT INTO looks like this:
INSERT INTO CompletedClassTable (ClassName, Teacher)
SELECT ClassName, Teacher FROM tblPending WHERE id = 123
And finally, you asked this in a comment:
So SELECT INTO is completely different in Access than Oracle? In Oracle and PL/SQL, you can select a row into a variable OR a table. In Access can you not select into a variable?
To load a row into a variable, you need to use a Recordset.
Example code to load your query into a Recordset and output the ClassName field:
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset("SELECT * FROM tblPending WHERE id = 123")
If Not RS.EOF Then
Debug.Print RS("classname")
End If
RS.Close
Set RS = Nothing
Seems you want to retrieve a text value, className, from tblPending where tblPending.id matches the value found in your text box, txtID, and store that text value in a string variable named cname.
If that interpretation is correct, you needn't bother with a query and recordset. Just use the DLookup Function to retrieve the value, similar to this untested code sample.
Dim cname As String
Dim pid As Integer
Dim strCriteria As String
pid = [Forms]![frmClasses]![txtID]
strCriteria = "id = " & pid
cname = Nz(DLookup("className", "tblPending", strCriteria), vbNullString)
Debug.Print "cname: '" & cname & "'"
Notes:
I assumed the data type of the id field in tblPending is numeric. If it is actually text data type, change strCriteria like this:
strCriteria = "id = '" & pid & "'"
DLookup() returns Null if no match found. Since we are assigning the function's return value to a string variable, I used Nz() to convert Null to an empty string. Alternatively, you could declare cname As Variant (so that it can accept a Null value) and get rid of Nz().