')' expected in vb - vba

I am trying to create a login form using Visual Basic and MS Access as my database source but I keep getting error as ')'expected. Please find my code below and help me solve this, because I have spent the entire day trying to find solution to this error.
sql =("SELECT Username,Password from tblLogin")
Where Username= '" & Trim(txtUsername.text) & "'
And Password='" & trim(txtPassword.text) & "')';

NEVER concatenate user inputs into any SQL statement, use proper parameters instead.
This means your SQL should look like this:
sql = "SELECT [UserName], [Password] FROM tblLogin WHERE [UserName]=? AND [Password]=?;"
Note that there is no need to track whether a column wants single quotes or not, which makes things much more robust, not to mention much more secure. Also the unbalanced parentheses issue becomes irrelevant.
The sql string should be used in some ADO Command or DAO (? ...not really familiar with Access) QueryDef object, as the command's CommandText or the querydef's definition.
Then you add Parameters to the ADO command and supply their values in the order they appear in the SQL command string, or set the named querydef parameters' respective Value accordingly.
Exactly how that's done depends on what type of Connection you're working with; this answer shows how you can use DAO QueryDefs in Access to do this, and this answer shows how you can use ADO to do the same with a Command and Parameter objects.
As a security note, I need to mention that storing password in plain text in a database is a very bad idea. Best practice would be to salt+hash the passwords, and only store the resulting hashes in the database; login is successful not when the user input matches the stored password, but when the salted user input produces the same hash value as the one stored for the claimed login: neither the code, the database, nor the developer actually needs to know anyone's passwords. This is important, because humans have this tendency to reuse passwords elsewhere, so if weak security isn't a problem for this particular application, it becomes a problem when a user decides to reuse their Facebook login for it, or to reuse their password for [other app whose security is actually important].

Try with:
sql ="SELECT Username, [Password] from tblLogin " & _
"Where Username = '" & Trim(txtUsername.Text) & "' " & _
"And [Password] = '" & Trim(txtPassword.Text) & "'";
Password is a reserved word.

Try replacing your line with this one instead:
sql = "SELECT Username,Password from tblLogin Where Username= '" &
Trim(txtUsername.text) & "'" & " And Password= '" &
trim(txtPassword.text) & "'"

Related

Why does MS Access prompt to enter parameter in update query which already has values?

I am making a database where the user can change the name of a company in a table. However , whenever I use the update query, it asks for a parameter which is already supplied. The old company name is in the variable new_comp and then the new one is in the Me.comp1_box.Value.
Funny enough the query runs excellently whenever I hit ok and enter nothing inside the "Enter Parameter" setting
Dim record_changer As String
record_changer = "UPDATE " & "[" & new_comp & "]" & " SET " & "[" & new_comp & "]" & ".Company_Name =" & """" & Me.comp1_box.Value & """" & ";"
MsgBox (record_changer)
DoCmd.RunSQL (record_changer)
This is the final value of the record_changer.
UPDATE [EREDEON TECHNOLOGIES] SET [EREDEON TECHNOLOGIES].Company_Name="EREDEON TECH";
This is how it is when the code runs.
This is the query that it is supposed to run
It gives this prompt meaning it's supposed to run perfectly, meaning there is nothing wrong with the Query
This what pops up
Can anyone please help me out?
I am genuinely lost.The name of the Old Company name is EREDEON TECHNOLOGIES and the new name is EREDEON TECH
But funny enough when I just hit Okay without entering a value into the parameter dialogue box, it actually makes the changes.-_- weird
This happens, then I press "OK"
THEN THIS HAPPENS, Then I hit Okay
This is the table before.
It updates the table the new value which is EREDEON TECH. When I just hit OK, without typing anything into Parameter Dialogue.
Try changing your SQL string to the following. Note the single quotes change around Me.comp1_box.Value.
record_changer = "UPDATE " & "[" & new_comp & "]" & " SET " & "[" & new_comp & "]" & ".Company_Name ='" & Me.comp1_box.Value & "';"
Misused quote marks is the most common cause for the Parameter Value prompt. If that doesn't work, use this article to perform step-by-step trouble shooting on all of the other usual causes, Why does Access want me to enter a parameter value?
You can also reference the following articles:
MS Docs, Quotation marks in string expressions
Bytes, (') and (") - Where and When to use them
Fundamentally, the issue is due to the use of double quotes in VBA which works in Access SQL by itself but not via VBA using DoCmd.RunSQL. You could have used single quotes to enclose company name value.
However, avoid concatenating VBA literals to SQL queries with quotes in the first place. Instead, use the industry best practice of parameterization which is available in MS Access using QueryDefs in VBA and PARAMETERS clause in SQL:
Dim record_changer As String
Dim qdef As QueryDef
sql = "PARAMETERS new_name_param TEXT; " _
& "UPDATE [" & new_comp & "] " _
& "SET Company_Name = new_name_param;"
' SET UP QUERYDEF
Set qdef = CurrentDb.CreateQueryDef("", sql)
' BIND PARAMS
qdef!new_name_param = Me.comp1_box.Value
' RUN ACTION
qdef.Execute
' RELEASE RESOURCE
Set qdef = Nothing
Nonetheless, the need to concatenate table name, new_comp, in query is questionable database design. Proper names (EREDEON TECHNOLOGIES, GAME DISCOUNT STORE, SHOPRITE, etc.) should never be names of tables. Avoid maintaining a separate table for every company. Instead, normalize data for a single table of all companies, then run UPDATE with WHERE adding a second parameter.
' PREPARED STATEMENT, NO VARIABLE CONCATENATION
sql = "PARAMETERS new_name_param TEXT, old_name_param TEXT; " _
& " UPDATE Companies " _
& " SET Company_Name = new_name_param" _
& " WHERE Company_Name = old_name_param;"
Set qdef = CurrentDb.CreateQueryDef("", sql)
qdef!new_name_param = Me.comp1_box.Value
qdef!old_name_param = new_comp
qdef.Execute
In fact, since above SQL is now separated from VBA, save the query without VBA punctuation (&, ", or _) as a separate object and call it in QueryDefs by name:
Set qdef = CurrentDb.QueryDefs("mySavedQuery")
qdef!new_name_param = Me.comp1_box.Value
qdef!old_name_param = new_comp
qdef.Execute
Even better, if your parameters derive from controls on open forms, include them directly in query for a single line VBA call. Below runs the normalized version of single Companies table:
SQL (save as query object, adjust names to actuals)
UPDATE Companies
SET Company_Name = Forms!myForm!comp1_box
WHERE Company_Name = Forms!myForm!new_comp
VBA (no need to close action queries)
DoCmd.OpenQuery "mySavedQuery"

Excel VBA database access through ODBC not ADODB

I am working on an Excel file that connects to a SQL database to update parameters on a piece of production machinery based on an analysis of part quality data. The file has been working in production for some time but a recent hacking attack on my company has caused us to review the security of all of our systems.
The old file version used ADODB with a hard-coded user name a password with narrowly defined database permissions. This meant any quality or engineering employee could run the Excel utility without being explicitly given server/database access. With our new security review, I wanted to switch the file to use windows authentication but I ran into some issues. It seems that using windows authentication through ADODB requires not just a database user, the automation team has permissions to create, but also a server login mapped to the database user which only an IT admin can create. I also worry that adding a large number of server-level users is not a wonderful idea.
The actual piece of production equipment uses a system-level ODBC connection with window authentication. This connection works fine with a database user without a server login. Because ODBC doesn't seem to need a server login it would make the management of the Excel file users much simpler and would allow the team in charge of the equipment and its database to handle it without IT.
Unfortunately, I have been unable to figure out how to execute queries and get results in VBA with an ODBC connection. I have tried Workbook.Connections("ODBCName").CommandText with an ODBC connection stored in the workbook but I don't see a way to directly get the result. The only option I can see is to map the query to cells in a hidden table and read them in VBA but this seems hackish. Also, I'm not sure how this would work for the results of queries other than SELECT like INSERT or UPDATE.
Any help would be greatly appreciated. An example of my old code is here, there are more routines that make similar queries:
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
strSQL = "SELECT * FROM Table.dbo.PART_INSPECTION_LOG WHERE PART_NUM = 'PartNo' AND DATA_TIME = " & dataTime
rs.Open strSQL, cn
If (rs.BOF And rs.EOF) = True Then
linear_err = (Sheets("Adjustment").Range("E24").Value)
rotational_err = (Sheets("Adjustment").Range("N24").Value)
strSQL = "INSERT INTO Table.dbo.PART_INSPECTION_LOG (PART_NUM, TOOL_ID, USER_NAME, DATA_TIME, LINEAR_ERROR, ROTATIONAL_ERROR) VALUES ('PartNum', 'ToolNum', "
strSQL = strSQL & "'" & Application.UserName & "', "
strSQL = strSQL & dataTime & ", "
strSQL = strSQL & linear_err & ", "
strSQL = strSQL & rotational_err & ")"
cn.Execute strSQL
End If
cn.Close

Error 2465 in MS Access when running a VBA code

Read through a few of the previously asked posts about this error but still cannot understand it.
The error text is "Run-time error '2465' CASREP reporting tool can't find the field '|1' referred to in your expression
I have a form to assign parts to certain supply reports. We have a form where users can manually hyperlink the parts to the request if they fall in the cracks. There is a check box feature, followed by the use of an "Assign" button to achieve this.
Every time a box is checked and a user selects "Assign" the error pops up. The string of code that pops up with the bug is as follows:
strSQL_del = "DELETE FROM [tbl_Temp_Assign] " & _
"WHERE [jcn_cd]= '" & Forms![Parts: Assign Unit].[tblTemp_Assign subform1].Form.[jcn.cd] & "'
AND [CASREP #] = '" & strCASREP & "' AND [doc_num_cd] = '" & Forms![Parts: Assign Unit].[tblTemp_Assign subform1].Form.[doc_num_cd] & "'
AND [last_updated_dte] = #" & Forms![Parts: Assign Unit].[tblTemp_Assign subform1].Form.[last_updated_dte] & "#
AND [PMOMsgDte] = #" & Forms![Parts: Assign Unit].[tblTemp_Assign Unit].Form.[PMOMsgDte] & "#" 'Intentionally left off AssignDte
Any help is greatly appreciated. I'm lost on what is wrong.
The error is related to the SQL string concatenation, but that string is quite long, it's hard to say if you have a space between ' and the first AND condition. Also, after the first continuation character _, is all that a single line?
Anyway, I would strongly advise to setup a delete query where you pass the form values as parameters and in VBA you just execute the query. It will be easier to update later on if needed.
The query:
PARAMETERS [prmTextField] Text (50), [prmDateField] DateTime, [prmNumberField] Long;
DELETE *
FROM T
WHERE T.TextField = [prmTextField]
AND T.DateField = [prmDateField]
AND T.NumberField = [prmNumberField];
Then, in VBA just execute the query.
With CurrentDb().QueryDefs("QueryName")
.Parameters("[prmTextField]").Value = '[Value from Form (text)]
.Parameters("[prmDateField]").Value = '[Value from Form (date)]
.Parameters("[prmNumberField]").Value = '[Value from Form (number)]
.Execute dbFailOnError
End With
By the way, do you really need to pass all those parameters to delete a record? Usually, just the record id is needed.

ASP classic & SQL (Syntax error in INSERT INTO statement.)

Getting this error when trying to add a new group using the information entered by the user.
Microsoft Access Database Engine error '80040e14'
Syntax error in INSERT INTO statement.
/student/s0190204/wip/group-add.asp, line 79
This is the sql, the session is getting the ID of the user logged in.
sql_comd="INSERT INTO group (grp_USERID, grp_name, grp_caption, grp_content, grp_DATECREATED, grp_OPEN) VALUES('" &_
session("usr_ID") & "','" & _
request("grp_name") & "','" & _
request("grp_caption") & "','" & _
request("grp_content") & "','" & _
date & "','" & _
request("grp_open") & "')"
Thanks
I suggest you trace this through, and post the output string that you're passing directly to SQL. Just put a breakpoint in there right as the string is created and check it out.
There's not much wrong with this code, persay, but you haven't made sure that your input strings are clean. It's probable that they have a quotation mark in them or the date isn't in the proper string format and so on.
Additionally, note that this query is highly susceptible to query injection because it seems to stuff input directly from the request through to the database.
OH, and. Your 'Insert INTO' needs Group in []. (like [Group]) And your dates should probably be DateTimes instead of strings. (if this works with just the brackets) See my note on your other question. (And avoid using these (http://technet.microsoft.com/en-us/library/ms189822.aspx) in your schema)
And you can set the 'default' of the date to '=GetDate()' instead of passing it through from the C# side, which I personally prefer.

SQL Injection vulnerablities in ASP script

Right now I have a sample ASP script below:
<%Set objConn = CreateObject("ADODB.Connection")
objConn.Open Application("WebUsersConnection")
sSQL="SELECT * FROM Users where Username=? & Request("user") & _"?and Password=? & Request("pwd") & "?
Set RS = objConn.Execute(sSQL)
If RS.EOF then
Response.Redirect("login.asp?msg=Invalid Login")
Else
Session.Authorized = True
Set RS = nothing
Set objConn = nothing Response.Redirect("mainpage.asp")
End If%>
May I know what kind of SQL Injection will be caused by this script? What's the result of the execution, and any sample SQL that can inject into application with the above script? It's extracted from the paper. Thanks
One of the problem of directly writing user input into a SQL query:
sSQL="SELECT * FROM Users where Username='" & Request("user") & "' and Password='" & Request("pwd") & "'"
is that if user submitted
username' OR 1=1 --
which makes your query eventually looks like this:
SELECT * FROM Users where Username='username' OR 1=1 --' and Password=''
depending on your database driver, this may return at least one row, making your script think this is a valid user (or even an admin, if defaultly sort by id ascending).
You can use ADODB.Command object to prepare SQL query and bind value to placeholder.
Something like this:
sSQL="SELECT * FROM Users where Username=? and Password=?"
set objCommand=CreateObject("ADODB.Command")
objCommand.Prepared = true
objCommand.ActiveConnection = objConn
objCommand.CommandText = sSQL
objCommand.Parameters.Append objCommand.CreateParameter("name",200,1,50,Request("user"))
objCommand.Parameters.Append objCommand.CreateParameter("password",200,1,64,Request("pwd"))
objCommand.Execute
MSDN doesn't seem to clear on whether ADODB.Command will actually treat query and value separately, but I guess for "modern" database driver, this is supported. If I remember correctly, this works on Oracle OLEDB database driver.
MSDN on ADODB.Command properties and methods
I have used the following two steps to protect against SQL injection with ASP for years on high traffic sites and never had an issue yet.
For each char datatype, make sure you replace any apostrophes with double apostrophes like this:
sql = "SELECT * FROM users WHERE "
sql = sql & "Username = '" & Replace(Request("user"), "'", "''") & "' "
sql = sql & "AND Password = '" & Replace(Request("pwd"), "'", "''") & "'"
For any number (non char) fields, verify that the input isNumeric first, otherwise ignore it, or return an error.
It is always good to use Regular Expressions to check for characters in the input (querystring / form variables / etc...) before you pass them onto your database for processing. The check should be done to see if all the characters in the input are within the allowed characters (whitelist check).
Function ReplaceRegEx(str, pattern)
set pw = new regexp
pw.global = true
pw.pattern = pattern
replaced = pw.replace(str, "") 'Find the pattern and store it in "replaced"
ReplaceRegEx = replace(str,replaced,"") 'Replace with blank.
End Function
'below is a sample. you can create others as needed
Function UserNameCheck(x)
UserNameCheck = ReplaceRegEx(x,"^[a-zA-Z_-]+$")
End Function
And this is how you call it in your ASP page:
fld_UserName=UserNameCheck(fld_UserName)
if fld_UserName="" then
'You can probably define the below steps as function and call it...
response.write "One or more parameters contains invalid characters"
response.write "processing stopped"
response.end
end if