I am using a VB program connected to an access database. In my code, I want to check if a record exists at the specified row, and if not, do something. Checking if the row exists is my issue. In pseudocode, this is what I want to achieve:
If RecordAtLocationExists = False Then
...
End If
Code I have tried includes:
If DBDataSet.Tables(TableName).Rows(QuestionNumber).IsNull = True Then
If DBDataSet.Tables(TableName).Rows(QuestionNumber) = "" Then
If DBDataSet.Tables(TableName).Rows(QuestionNumber) = Nothing Then
If DBDataSet.Tables(TableName).Rows(QuestionNumber) = Null Then
None of the above code works. I have tried to search for a solution, but everything else seems far too complicated for this. I am probably approaching this wrong, but hopefully it makes sense what I am trying to achieve.
Any ideas?
First of all, you are trying to check if the record exists at a DataTable, not at database. Database data could have changed since you filled your DataTable. Try to query the database directly:
Dim specificRow as Integer = 23 '<-- Set this variable to the specific row you are looking for
Dim query As String = "SELECT * FROM TableName WHERE QuestionNumber = ?"
Dim cmd As OleDbCommand = New OleDbCommand(query, myConnection)
cmd.Parameters.AddWithValue("questionnumber", specificRow)
dr = cmd.ExecuteReader
And test if the command return rows
If dr.Read() Then
' Do stuff here
Else
' Do another stuff here
End if
Related
JUST A HEADS UP ----- This no longer applies for me. I fixed it by adding the following two lines to my form.load.
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
It has fixed the issue for me and I hope it sorts it out for you too.
Okay, so, I have an application in VB.net that serves as a scheduler for the trainers at the company I work at. In the edit mode (so updates can be made to the database the information is stored on) there are a number of buttons, adding and removing trainers, or adding weeks to the table.
The button causing me problems is the save/update button. It has three sets of commands within it, one for updating added columns, one for removed columns, and then a third one which simply updates other modified data. I know it probably could be more efficient but oh well, I'll get to that later.
The problem is, the last chunk of code includes "da.update(ds)" which is the data adapter updating the datasource. While this command works perfectly fine in our other app that connects to our SQL server, its causing problems here.
Any column where the first cell's value is null causes an exception saying
"Incorrect syntax near 'the column header's first two characters'."
Now, I thought this issue stemmed from - due to the exception - me using an incorrect set of names for the columns, which were the dates of the mondays of each week (so for example 01/02/2016) so it'd show Incorrect syntax near '01'. in this instance.
However, changing the naming convention did not fix this like how the exception would suggest, and it only occurs on columns where the FIRST value is a null - implying that the first trainer has nothing planned for this week right now.
Anyone have any ideas as to a way around this that doesnt involve basically filling in every null on this rather large table? I know that would work but It'd be pretty time consuming, and I am willing to do this if no other solution rears its head.
I've looked around on the internet and haven't found a solution that appeared relevant to our exact issue, so help would be very appreciated.
In case it is important - here is the function causing the issue.
Dim da As OleDbDataAdapter 'The datasets and adapters variables.
Dim da2 As OleDbDataAdapter
Public ds As DataSet = New DataSet
Public ds2 As DataSet = New DataSet
'Connection String. Connects to the server and finds the database and table listed.
cs = "Provider=SQLOLEDB;"
cs &= "Server=SOFWAREDEVSQLSE\SQLEXPRESS;"
cs &= "Database=MTS2;"
cs &= "User Id=;" 'You don't need to see that to be fair.
cs &= "Password=;" 'You don't need to see that to be fair.
sql = "Select * FROM MTS2;"
'Runs the string. Flares up a timed out error if connection could not be established.
Try
da = New OleDbDataAdapter(sql, cs)
da.Fill(ds)
da2 = New OleDbDataAdapter(sql, cs)
da2.Fill(ds2)
Catch ex As Exception
MsgBox("Connection failed. Please ensure you have a suitable connection to the Training network. Otherwise, refer to helpdesk support for further assistance.")
Me.Close()
End Try
dgvSchedule.DataSource = ds.Tables(0)
Private Function save()
'Try
''This section reads the SQL server for column names, and adds any that are listed in the DGV, but not the database. I know its a little messy but itll do.
Dim columnnum As Integer = -1
Dim columname As String
For Each column In ds.Tables(0).Columns
columnnum = columnnum + 1
columname = dgvSchedule.Columns(columnnum).HeaderText
If Not ds2.Tables(0).Columns.Contains(columname) Then
Dim SqlAddCol As String = "ALTER TABLE MTS2 ADD [" & columname.Trim() & "] nvarchar(255)"
Using con As New OleDbConnection(cs)
Using cmd As New OleDbCommand(SqlAddCol, con)
con.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End If
Next
columnnum = -1
For Each column In ds2.Tables(0).Columns
columnnum = columnnum + 1
columname = ds2.Tables(0).Columns(columnnum).ColumnName
If Not ds.Tables(0).Columns.Contains(columname) Then
Dim SqlDelCol As String = "ALTER TABLE MTS2 DROP COLUMN [" & columname.Trim() & "]"
Using con As New OleDbConnection(cs)
Using cmd As New OleDbCommand(SqlDelCol, con)
con.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End If
Next
ds2.Tables.Clear()
da2 = New OleDbDataAdapter(sql, cs)
da2.Fill(ds2)
da.Update(ds) ''''' The exception is thrown here. " Incorrect syntax near '01'."
DataTableColours()
MessageBox.Show("Data saved successfully. New weeks and trainers added and deleted. Changed values updated.")
'Catch
' MessageBox.Show("Data failed to update properly. Please ensure you are connected to the Baltic network and try again. If the problem persists, seek IT support.")
'End Try
End Function
The function saves the values in the data grid view (DGVSchedule) to the server by taking the current columns in the DS with their original columns (which are in DS2) A Sql query is then ran to add or remove any column mismatches. DS2 is then updated to use the same values as DS. Finally, DA.update(DS) is called, which updates all other modified values into the SQL server - theoretically. It is instead causing our peculiar exception.
Any help would be greatly appreciated, thanks.
I have fixed the problem I was encountering. I fixed it by adding the following two lines to my form.load.
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
Basically, I feel like a dumbass now but this solved the problem.
I had confusion with my code:
Dim sqladapter As SqlDataAdapter = New SqlDataAdapter()
Dim sqlcmd As SqlCommand = New SqlCommand()
sqlcmd = New SqlCommand("SELECT login, pass from Table1 where login=" & login.Text & "and pass='" & password.Text.ToString() & "';", connect)
Dim dr As SqlDataReader = sqlcmd.ExecuteReader()
Dim dt As DataTable = New DataTable()
dt.Load(dr)
If (dt.Rows.Count = 1) Then
'Display welcome page or do some action here.
Now, my question is, is there any other way of doing Rows.Count==1 . I'm feeling that it is very wrong and makes no sense at.
How do you verify from database that a user has only one valid record in table other than counting rows.
Thanks in Advance :)
(Please ask me before reporting question)
You have two problems, one is called Sql Injection and you have already numerous links that explain why is really bad. Another one is the plain text password stored in your database. This is a big security concern because everyone that has the possibility to look at your database could see the passwords of your users. (The gravity of this, of course, is linked to the nature of your application but cannot be downplayed) See this link for an answer on how to hash a string (a password) and get its encrypted version to store in the database instead of the plain text.
Finally the code you use could be changed to avoid both the SqlDataAdapter and the DataTable.
Just use an ExecuteScalar against an IF EXIST query that return just 1 if the user/password exists or zero if not
Dim cmdText = "IF EXISTS(SELECT 1 FROM Table1 WHERE login = #log AND pass = #pwd) " & _
"SELECT 1 ELSE SELECT 0"
using connect = new SqlConnection(connectionstring)
using sqlcmd = New SqlCommand(cmdText, connect)
connect.Open()
sqlcmd.Parameters.AddWithValue("#log", login.Text)
sqlcmd.Parameters.AddWithValue("#pwd", password.Text) ' <- Subst with a call to an hash function
Dim exists = Convert.ToInt32(sqlcmd.ExecuteScalar())
if exists = 1 Then
'Display welcome page or do some action
else
end if
End Using
End Using
There is only one way to answer to the question and its to count rows. The different solution would be to count them in database. For example you could write stored procedure that takes username and password and returns boolean this way you would drag less data.
As a side note there is potential sql injection in your code. You should not store clear password in database. You should return the whole row and match hash of the password from database to the hash of the paasword that you get from UI.
I got an SQL 2005 table with many (84 to be specific) fields (actually it is a query returned by a procedure)
It looks like when I access recordset fields placed later then some field placed earlier becomes empty while server had actually returned a value for it
Had anyone such problem?
My solution is to put such disappeared field at the end of a table so when it is accessed later by a code (here VBA) its value is still accessible BUT I see it as a big problem in ADODB.Recordset 2.8 as I should not care about field order
I know that question is not very specific but maybe someone had a similar issue?
One way to to make sure the field values are there is to pass on the recordset to a array like (You will have to build your own connection function):
Function getStoredProcedure() As Variant
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim values As Variant
Set conn = getConn("Server", "Database")
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "StoredProcedureName"
cmd.Parameters.Item("#TODAY") = today
Set rs = cmd.Execute
If Not rs.EOF Then
values = rs.GetRows
Else
Exit Function
End If
Set cmd = Nothing
getStoredProcedure= transposeArray(values)
End Function
From there you can always retrieve the values from the array. Otherwise, without seeing your code or understand what you are trying to do, I cannot tell if this is really an issue with ADODB because I cannot recreate this issue when pulling field items in any order I want such as: rs.Fields.Item(i).Value for i = any number in any order.
I met this problem twice. There are two exception fields in my query string. Running the query string in sql server, they can return the values but these two exception fields are empty when run the query string in VBA used recordset. I put these exception fields behind other normal fields in the query string, and then they can return value in the recordset instead of blank. So it's really a big problem.
Dim sqlCountQuery As String = "SELECT COUNT(*) FROM codes"
Dim SQLConnection As MySqlConnection = New MySqlConnection
Dim CountCommand As New MySqlCommand(sqlCountQuery, SQLConnection)
SQLConnection.ConnectionString = strServerString
SQLConnection.Open()
reader = CountCommand.ExecuteReader
reader.Read()
CodeCounter = reader.GetInt32(0)
SQLConnection.Close()
Dim sqlQuery As String = "SELECT * FROM codes"
Dim Command As New MySqlCommand(sqlQuery, SQLConnection)
SQLConnection.Open()
reader = Command.ExecuteReader()
reader.Read()
For b = 0 To CodeCounter - 1
test = reader.GetInt32(b)
Next
The top bit of code retrieves the number of codes currently stored in the database but when I move on to the second part with the for loop, it correctly retrieves the first code from the database, but after that I get an error saying "You have specified an invalid column ordinal.". I have been running it line by line which is how I know it retrieves the first code correctly.
You mixed up the number of columns to the number of rows. CodeCounter is the row count but in second part of code you tried to get data from column. reader.GetInt32(int) gets data from given column.
All code written in a very bad. Examin this article with example for information how to use DataReader. Article for SQL Server data provider but it can be helpful for you.
I am making a booking system application for a sports club. In my SQL Server database, I have two tables; one is named Memberships and the other is named Bookings.
Now, what I want is to allow a new booking for only those customers who have a membership. In the database I have joined both tables by the cust_id attribute where the Memberships table is parent and Bookings table is child. I want that when a new booking is tried, then it should first check if the customer ID is present in database. If it is present, then the booking should be allowed, otherwise not. But, my code shows an error first and then allows the booking
Here is my code for this:
Dim i As Integer
Dim str2 As String ' defines string variable for taking select query
str2 = "select Memberships.cust_id, booking_date, booking_time, booking_duration, game, poolno, courtno, tableno from Bookings, Memberships where Memberships.cust_id = Bookings.cust_id"
i = -1
Dim cmd2 As New SqlCommand(str2, con) 'defines a new sql command with str2 as query string and con as connection string
con.Open() 'sets the connection state to open
Dim bookchk As SqlDataReader = cmd2.ExecuteReader 'Defines and initiates the datareader to read data from database using cmd2 command
While bookchk.Read()
If Me.MskdTxtCustId.Text = bookchk("cust_id") Then
i = 1
End If
End While
bookchk.Close()
con.Close()
If i = -1 Then
MessageBox.Show("Error")
Exit Sub
End If
Why dont you just ask for the customers membership number before they can make a booking?
Otherwise you could make membership number a required field.
I could understand if you'd got as far as checking the database if it was a case of checking if the membership number they gave was valid, otherwise check for required data before connecting to a database.
Try this:
Dim sql As String
Dim customerIDyouWantToCheck As String
Dim i As Integer
i = 0
sql = "select cust_id from Memberships where Memberships.cust_id = '" & customerIDyouWantToCheck & "'"
Dim cmd2 As New SqlCommand(str2, con)
con.Open()
Dim bookchk As SqlDataReader = cmd2.ExecuteReader
If bookchk.HasRows() Then
i = 1
Else
i = -1
EndIf
I'm assuming you know the ID of the customer who you want to make a booking for. Otherwise I'm not sure what you're doing.
The best way to deal with anything like this is to ensure the database returns what you want first. Have you tried the run the query directly against sql-server?
What you really need is to check the customers ID in the Membership table first, and once the correct customer is established separately go ahead an insert into the Bookings table. These are both atomic transactions.
I think you are making this simply problem too complex.
Loading all booking/membership combinations and looping through them to find a certain customer ID is bad practice.
It is better to query for the desired customer ID directly. Plus, you should use SQL parameters instead of string concatenation to pass the customer ID to the query.
Before:
str2 = "select [...] where Memberships.cust_id = Bookings.cust_id"
i = -1
Dim cmd2 As New SqlCommand(str2, con)
After:
str2 = "select [...] where Memberships.cust_id = Bookings.cust_id and Bookings.cust_id = #CustomerID"
i = -1
Dim cmd2 As New SqlCommand(str2, con)
cmd2.Parameters.Add(New SqlParameter("#CustomerID", SqlDbType.Int).Value = Me.MskdTxtCustId.Text)
Regarding your actual problem:
but my code either shows error first and then allows the booking
As you didn't show the code that does the booking and how it is connected to the code you showed, we can't tell how you use the result from the code you posted to determine if the booking is done or not.
You should wrap the code that you posted in a method that returns true or false, depending whether the booking is allowed or not.
'the CustomerHasMembership() method contains the code you posted and
'returns true when the customer DOES have a membership
If CustomerHasMembership(Me.MskdTxtCustId.Text) Then
DoBooking()
End If