Hey guys I have to extract some values from my DB and put them on my textbox. There's a problem at :
TextBox1.Text = TextBox1.Text & DR.Item("id") & Space(3) & DR.Item("Nume") & Space(3) & DR.Item("COUNT(pontaj.prezente)")
Error in VB:
This is how my select looks like:
Dim dbCon = New MySqlConnection("Server = localhost;Database = users; Uid=root; Pwd = password ")
'SELECT users1.id,users1.Nume, COUNT(pontaj.prezente) FROM users1, pontaj WHERE users1.id = pontaj.id
Dim strQuery = "SELECT users1.id,users1.Nume, COUNT(pontaj.prezente)" & _
"FROM users1, pontaj "
Dim SQLCmd = New MySqlCommand(strQuery, dbCon)
' Pwd = password
' Open
dbCon.Open()
Dim DR = SQLCmd.ExecuteReader
TextBox1.Text = TextBox1.Text & DR.Item("id") & Space(3) & DR.Item("Nume") & Space(3) & DR.Item("COUNT(pontaj.prezente)") & vbCrlf
While DR.Read
End While
'Close
DR.Close()
dbCon.Close()
Well, the error is clear, you cannot access the fields of a DataReader before calling Read.
The call is required to position the reader on the first record returned by the query and then to advance on the subsequent records until you reach the end of the returned records.
Also the syntax for your query seems incorrect and the way you reference the third column of your query
Dim dbCon = New MySqlConnection(............)
Dim strQuery = "SELECT users1.id,users1.Nume, COUNT(pontaj.prezente) as countPrezente " & _
"FROM users1 INNER JOIN pontaj ON users1.id = pontaj.id " & _
"GROUP BY users1.id, users1.Nume"
Dim SQLCmd = New MySqlCommand(strQuery, dbCon)
dbCon.Open()
Dim DR = SQLCmd.ExecuteReader
' If Read returns true then you have one or more record to show'
While DR.Read()
TextBox1.Text = TextBox1.Text & _
DR.Item("id") & Space(3) & _
DR.Item("Nume") & Space(3) & _
DR.Item("countPrezente") & vbCrlf
End While
DR.Close
dbCon.Close
Looking at your previous question, the Foreign Key between users1 and pontaj is named id, so I have used an explicit join between the two tables to link the records from the two tables
Related
Good day! Can someone help me fix my code? I would like to show an error message if there is a duplication of record. For example, I entered a username "admin" but it is already in my database so it should show a message saying "Username already exists!". Otherwise, If the username isn't used yet then it will be added in my database. I'm using Visual Studio 2005 and Navicat for MySQL
Here is my code:
conn.Open()
Dim qadd As String = "SELECT * FROM tbl_user WHERE uname='" & txt_uname.Text & "'"
Dim cmd As New MySqlCommand(qadd, conn)
Dim data As MySqlDataReader = cmd.ExecuteReader
If data.Read Then
If data(0) = txt_uname.Text Then
MsgBox("User " & data(0) & " already exists! ", MsgBoxStyle.Critical)
Else
Dim qstr As String = "INSERT INTO tbl_user (uname, pword, ulvl) VALUES ('" & txt_uname.Text & "' , '" & txt_pword1.Text & "' , '" & txt_pword2.Text & "') ON DUPLICATE KEY UPDATE uname = '" & txt_uname.Text & "'"
Dim cm As New MySqlCommand(qstr, conn)
Dim dat As MySqlDataReader = cm.ExecuteReader
MsgBox("User has been added!", MsgBoxStyle.Information)
txt_uname.Clear()
txt_pword1.Clear()
txt_pword2.Clear()
txt_uname.Focus()
End If
End If
conn.Close()
Still a lot of room for improvement, and I typed this out on my phone with no syntax checking, but think it should get you heading in the right direction. Things for you to read up on is parametrising your query/insert statements and the Using keyword which can help with managing your db connections.
Dim qadd As String = "SELECT Count(uname) FROM tbl_user WHERE uname='" & txt_uname.Text & "'"
Dim cmd As New MySqlCommand(qadd, conn)
Dim userCounter as int = cmd.ExecuteScaler
if userCounter > 0 then
MsgBox("User " & data(0) & " already exists! ", MsgBoxStyle.Critical)
Else
Dim qstr As String = "INSERT INTO tbl_user (uname, pword, ulvl) VALUES ('" & txt_uname.Text & "' , '" & txt_pword1.Text & "' , '" & txt_pword2.Text & "') ON DUPLICATE KEY UPDATE uname = '" & txt_uname.Text & "'"
Dim cm As New MySqlCommand(qstr, conn)
Dim dat As MySqlDataReader = cm.ExecuteReader
MsgBox("User has been added!", MsgBoxStyle.Information)
txt_uname.Clear()
txt_pword1.Clear()
txt_pword2.Clear()
txt_uname.Focus()
End If
Sub Get_Data()
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim dateVar As Date
Set conn = New ADODB.Connection
conn.ConnectionString = "DRIVER={MySQL ODBC 5.1 Driver}; SERVER=localhost; DATABASE=bi; UID=username; PWD=password; OPTION=3"
conn.Open
strSQL = " SELECT " & _
" Products " & _
" FROM Logistics " & _
" WHERE DATE(insert_timestamp) = ""2020-02-24"" " & _
" GROUP BY 1"
Set rs = New ADODB.Recordset
rs.Open strSQL, conn, adOpenStatic
Sheet5.Range("A1").CopyFromRecordset rs
rs.Close
conn.Close
End Sub
I run the above VBA to extract values fom the database.
It works exactly how I need it.
Now, instead of having a pre-defined date within strSQL I want to use the data that is entered into Cell B1 in my Excel spreadsheet. Therefore, I changed the strSQL part in the VBA to:
strSQL = " SELECT " & _
" Products " & _
" FROM Logistics " & _
" WHERE DATE(insert_timestamp) = " & Sheet1.Range("B1") & " " & _
" GROUP BY 1"
However, now I get runtime error -2147217887 (80040e21) on rs.Open strSQL, conn, adOpenStatic.
What do I need to change in my VBA to make it work?
Consider the industry best practice of SQL parameterization using the ADO Command object which can properly handle data types without string concatenation or various formatting:
Dim conn As ADODB.Connection ' REMOVE New INITIALIZATION IN Dim LINES
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim dateVar As Date
Set conn = New ADODB.Connection
conn.ConnectionString = "DRIVER={MySQL ODBC 5.1 Driver}; ..."
conn.Open
' STRING STATEMENT WITH QMARK PLACEHOLDER
strSQL = " SELECT " & _
" Products " & _
" FROM Logistics " & _
" WHERE DATE(insert_timestamp) = ?" & _
" GROUP BY Products"
' CONVERT CELL TO DATE TYPE (IF CELL FORMATTED AS STRING)
dateVar = CDate(Sheet1.Range("B1").Value)
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = strSQL
.CommandType = adCmdText
' BIND PARAMS TO QMARK POSITIONAL PLACEHOLDER
.Parameters.Append .CreateParameter("mydate", adDate, adParamInput, , dateVar)
' PASS RESULT TO RECORDSET
Set rs = .Execute
End With
Sheet5.Range("A1").CopyFromRecordset rs
Try:
strSQL = " SELECT " & _
" Products " & _
" FROM Logistics " & _
" WHERE DATE(insert_timestamp) = '" & Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "' " & _
" GROUP BY 1"
Just be aware, if insert_timestamp does indeed contain a time other than midnight, you might not get the results you're after without converting to just a date or altering your SQL.
I have a table in Access with the relevant fields EFTRecID, EFTRecIDNum and CreatedBy. EFTRecIDNum is an auto number field, and EFTRecID concatenates the required format of "CE" & EFTRedIDNum. I am attempting to return the highest value in the EFTRecID field that was created by the current user. To do this I am trying to do a sub query that finds the Max(EFTRecIDNum) WHERE Created = my name. However instead of returning the max, it is returning all values with my name. I know I could use the format option to just format the EFTRecIDNum field, but I need to be able to search in the format CE456.
TL;DR: Query returns all records with my name, rather then max with my name.
Public Sub DownloadMyRecords()
Dim intI As Integer 'Used for looping in a variety of locations
strSQL = "SELECT EFTRecID FROM tblEFTRec WHERE (SELECT MAX(EFTRecIDNum) FROM tblEFTRec WHERE CreatedBy = '" & Application.UserName & "')"
Set cnn = New ADODB.Connection
With cnn
.Provider = "Microsoft.ACE.OLEDB.12.0;Data Source=" & dbLocation & "\" & dbName & ";Jet OLEDB:Database Password=" & DBPWord
.Open dbLocation & "\" & dbName
End With
Debug.Print strSQL
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseServer
rst.Open Source:=strSQL, ActiveConnection:=cnn, _
CursorType:=adOpenForwardOnly, LockType:=adLockOptimistic, _
Options:=adCmdText
Debug.Print (rst.GetString)
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
End Sub
Try this SQL statement instead:
strSQL = "SELECT EFTRecID
FROM tblEFTRec
WHERE EFTRecIDNum = (SELECT MAX(EFTRecIDNum) FROM tblEFTRec WHERE CreatedBy = '" & Application.UserName & "')"
Try using:
"SELECT EFTRecID FROM tblEFTRec
WHERE EFTRecIDNum = (SELECT MAX(EFTRecIDNum) FROM tblEFTRec
WHERE CreatedBy = '" & Application.UserName & "')"
Is there a reason the following doesn't work?
"SELECT MAX(EFTRecID) FROM tblEFTRec
WHERE CreatedBy = '" & Application.UserName & "'"
I am writing a macro by which I want to delete few names in column A of sheet 2 from the server table called login.
Database name is "my_db" and table name is login. I calling connection to connect to the server databse. Following is the complete code :-
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim Sql As String
Sub Button1_Click()
Dim Ws As Worksheet
Dim Var As String
Dim i As Integer
i = 1
Set Ws = Worksheets("Sheet2")
Var = "login"
Sql = "name"
Call Connection
Do
Sql = " Delete From " & " " & Var & "" & " Where name" = "Ws.Cells(i, 1)"
Call Connection
i = i + 1
Loop Until Ws.Cells(i, 1) = ""
MsgBox "All entries deleted from login table"
End Sub
Dim strUserName As String
Dim strPassword As String
Dim ConnectString As String
Set cnt = New ADODB.Connection
strServerName = "localhost"
strDatabaseName = "my_db"
strUserName = "root"
strPassword = "root1"
ConnectString = "DRIVER={MySQL ODBC 5.1 Driver};" & _
"SERVER=" & strServerName & _
";DATABASE=" & strDatabaseName & ";" & _
"USER=" & strUserName & _
";PASSWORD=" & strPassword & _
";OPTION=3;"
With cnt
.CursorLocation = adUseClient
.Open ConnectString
.CommandTimeout = 0
Set rst = .Execute(Sql)
End With
'rst.Close
'cnt.Close
Set rst = Nothing
Set cnt = Nothing
End Sub
But the entries are not getting deleted. There is an error in SQL syntax, can anyone help me with the sql syntax ?
Sql = "delete From " & Var & " where name ='" & Ws.Cells(i, 1).Value & "'"
but it would be better to open the connection only once, run all the deletes, and then close the connection.
Also you don't need a recordset here (since you're not returning any records), so you can ignore the return value from cnt.Execute
Since you pasted the code only partially, I can only guess.
Do
Sql = " Delete From " & Var & " Where name" = "Ws.Cells(i, 1)"
Call Connection (Sql)
i = i + 1
Loop Until Ws.Cells(i, 1) = ""
Clean up your query. And more important pass it as a parameter to the connection.
Quick one for you.
I'm using the following code to insert a record into two tables in my mysql db...
SQLConnection.ConnectionString = connectionstring
Try
If SQLConnection.State = ConnectionState.Closed Then
SQLConnection.Open()
Dim SQLStatement As String = "INSERT INTO hosts(name, description, host, type, port, hostname) VALUES('" & txtname.Text & "','" & txtdescription.Text & "','" & txthost.Text & "','" & cmbtype.Text & "','" & txtport.Text & "','" & Pinger.resolvedstatus.Text & "'); SELECT LAST_INSERT_ID()"
SaveData(SQLStatement)
SQLConnection.Open()
SQLStatement = "INSERT INTO credentials(hosts_linked_id, username, password, type) VALUES('" & hosts_linked_id & "','" & txtusername.Text & "','" & txtpwd.Text & "','" & cmbtype.Text & "')"
SaveData(SQLStatement)
the Savedata() bit calls this function...
Public Sub SaveData(ByRef SQLStatement As String)
Dim cmd As MySqlCommand = New MySqlCommand
cmd.CommandText = SQLStatement
cmd.CommandType = CommandType.Text
cmd.Connection = SQLConnection
cmd.ExecuteNonQuery()
hosts_linked_id = CInt(cmd.ExecuteScalar())
SQLConnection.Close()
MsgBox("Host has been added - Host ID " & hosts_linked_id & "")
txtname.Text = ""
txtdescription.Text = ""
txthost.Text = ""
cmbtype.Text = ""
txtport.Text = ""
End Sub
The code is working in that the necessary records are inserted into both the 'hosts' and 'credentials' tables, however in each table the record is inserted twice.
obviously I don't want duplicate records in my db, so can anyone help me stop it from performing the insert twice?
Thanks in advance!!
You call it twice:
cmd.ExecuteNonQuery()
hosts_linked_id = CInt(cmd.ExecuteScalar())
Once as ExecuteNonQuery and second time as ExecuteScalar()
You need to remove one of them. Looking at the code, I guess maybe you need to introduce a parameter to SaveData method to say which one to use.
cmd.ExecuteNonQuery()
hosts_linked_id = CInt(cmd.ExecuteScalar())
Remove cmd.ExecuteNonQuery() To avoid Insert Twice