I have ASP code with MS Access and I am updating my records. While updating when I put special characters like single quotes(') in string it displays an error. When string is without special chars it works correctly.
Please help or give any solution. Here is my code.
<!--#INCLUDE FILE="ConnStr.asp"-->
dim fileTitle
dim fileDescription
dim fromDateX
dim toDateX
dim romTimeX
dim toTimeX
dim Location
dim LocationURL
dim FileID
fileTitle= request("fileTitle")
fileDescription= request("description")
fromDateX= request("fdate")
toDateX= request("tdate")
romTimeX= request("ftime")
toTimeX= request("ttime")
Location= request("location")
LocationURL= request("locationurl")
FileID= request("jID")
sql = "Update tblFileInfo Set sFDate='" & fromDateX & "',sTDate='" & toDateX & "', sFTime='" & romTimeX & "',sTTime='" & toTimeX & "',location='" & Location & "', locationURL='" & LocationURL & "', filetitle='" & fileTitle & "', description='" & fileDescription & "' Where ID=" & FileID
objConn.Execute(sql)
Response.Redirect("adminfiles.asp?msg=save")
As previous answer mentions, you should avoid updating or accessing your database in this way due to SQL injection.
If your script is just for a temporary database update and for personal use, the quick and dirty way is to escape the apostrophe by repeating it again with a Replace function.
sql = "Update tblFileInfo Set sFDate='" & Replace(fromDateX,"'","''") & "' ...."
OR replace with HTML equivalent.
sql = "Update tblFileInfo Set sFDate='" & Replace(fromDateX,"'","'") & "' ...."
Do not use this for anything but a quick one off scripts if you're strapped for time. Not recommended under any other circumstance.
Don't insert parameter values like this, be aware of SQL injections!
Use ADO Command with parameters or create a stored procedure that handles the insert/ updates. Both solutions will solve your problem with single quotes. A good example can be found here: http://www.xtremevbtalk.com/showthread.php?t=309329#post1337389
Related
I am trying to build this query through VBA instead of building it in Access and running a docmd.openquery. That seemed to me like the easier route, but I wanted to work on my SQL. Obviously that didn't work as intended if I am here lol.
So, I am trying to take the Date values of 14 text boxes on our JobTicket form and insert them into another table, Tbl_Schedule. This table is not a part of the Query that is the record source for the JobTicket form. I am worried that attempting to add this table in will overload the Query, as it is already very full. When I try to quickly navigate to the last field in that Query the text writes on top of itself, and then Access goes not responding while it clears up the text and loads the last couple fields. Adding another 56 fields to that seems like a recipe for disaster. I will post the SQL I have written below.
DoCmd.RunSQL "INSERT INTO Tbl_Schedule (Date_Scheduled1, Date_Scheduled2, Date_Scheduled3, Date_Scheduled4, Date_Scheduled5, Date_Scheduled6, Date_Scheduled7, " & _
"(Date_Scheduled8, Date_Scheduled9, Date_Scheduled10, Date_Scheduled11, Date_Scheduled12, Date_Scheduled13, Date_Scheduled14)" & _
"VALUES (#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled1_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled2_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled3_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled4_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled5_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled6_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled7_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled8_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled9_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled10_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled11_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled12_JobTicket] & "#, " & _
"(#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled13_JobTicket] & "#,#" & [Forms]![Frm_JobTicket]![Txt_DateScheduled14_JobTicket] & "#)"
Table being inserted into: Tbl_Schedule
Fields being inserted into: Date_Scheduled1 -to- Date_Scheduled14
Getting data from text boxes: Txt_DateScheduled1_JobTicket -to- Txt_DateScheduled14_JobTicket on Frm_JobTicket
Any other questions that would assist you in assisting me please feel free to ask! Thanks in advance!
Dynamic SQL has its uses, but this is not one of them.
Using DAO methods makes your code so much simpler and easier to read and debug.
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim frm As Access.Form
' for readability
Set frm = Forms!Frm_JobTicket
' open table for adding record(s)
Set db = CurrentDb
Set rs = db.OpenRecordset("Tbl_Schedule", dbOpenDynaset, dbAppendOnly)
rs.AddNew
rs!Date_Scheduled1 = frm!Txt_DateScheduled1_JobTicket
rs!Date_Scheduled2 = frm!Txt_DateScheduled2_JobTicket
' etc.
rs.Update
rs.Close
With enumerated field names like these, you can also use a loop:
Dim i As Long
rs.AddNew
For i = 1 To 14
rs("Date_Scheduled" & i) = frm("Txt_DateScheduled" & i & "_JobTicket")
Next i
rs.Update
This is a good opportunity to consider normalizing your data so that part of your problem is removed entirely. Instead of having DateScheduled1_JobTicket, DateScheduled2_JobTicket etc., it might be better to have another table which fills vertically instead of horizontally, perhaps with fields like ID, Item, JobTicketNumber, ScheduledDate.
Then, fill this table with a row for each item/sku/product, and date. You'll have 14 rows for scheduled tickets for each item/sku/product instead of 14 columns, and this will also solve your future problem of adding 56 fields. The benefit is that you can present the job ticket schedule rows by using continuous forms (in a list). Even better, you can put this continuous form with dates as a subform on your item/sku/product main form, which will then show as a neat list of scheduled tickets that will automatically change as you scroll through item/sku/products.
If you don't use continuous forms, you can still use an unbound approach as you're using now. One benefit is that it will be much easier when you need to add future JobTicket numbers, since you can just add more rows instead of adding fields and having to do additional design work.
If you want to view data in the flattened way that you built your table, you can use a Crosstab query to present it as you have in your table, but the underlying data will be much better stored in a normalized format.
Note that you don't need to concatenate a string as you did above; just leave the Forms!Form!Control reference expression directly in the query and you have a nice parameterized query that will execute just fine, so long as there are dates in those controls (text box, drop down etc).
ex.
Insert Into (MyDateField) Values (Forms!MyForm!MyDateControl);
No dynamic SQL needed.
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"
I have created a query that works great with no errors in Access, and while trying to translate this to my vba setup I can't figure out why I am not getting any values, even though the query clearly works in access, and causes no errors on the VBA side.
Pulling my hair out here, I have created a side table to see if I could "pseudo-insert" the calculated value, but I get the same issue as above - insert works with no errors in access, goes through in vba with no issues, but doesn't actually insert any data.
I have copied the string queries while pausing code to make sure EVERYTHING matches up between the Access query that works and the VBA query, and haven't found any differences.
I read somewhere since I am trying to pull a "first line" data piece that there may be some HDR setting that I could change, but when I tried to apply any fixes I found they opened another instance of excel and opened a dialogue box.
Please let me know what I am doing wrong here.
Public Function PullNextLineItemNumB(QuoteNum) As Integer
Dim strQuery As String
Dim ConnDB As New ADODB.Connection
Dim myRecordset As ADODB.Recordset
Dim QuoteModifiedNum As String
ConnDB.Open ConnectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data
source=" & ThisWorkbook.Path & "\OEE Info.accdb"
'Query to try and make Access dump the value "18" into the table so I can
grab it after the query is finished, sidestepping excel not working
strQuery = "INSERT INTO TempTableColm (TempColm) SELECT
MAX(MID([Quote_Number_Line],InStr(1,[Quote_Number_Line]," & Chr(34) & "-"
& Chr(34) & ")+1)) AS MaxNum from UnifiedQuoteLog where Quote_Number_Line
like '" & QuoteNum & "*'"
ConnDB.Execute strQuery
'Original query, returns "18" as expected in Access, and null or empty in
the recordset
strQuery = "SELECT MAX(MID([Quote_Number_Line],InStr(1,
[Quote_Number_Line]," & Chr(34) & "-" & Chr(34) & ")+1)) from
UnifiedQuoteLog where Quote_Number_Line like '" & QuoteNum & "*'"
Set myRecordset = ConnDB.Execute(strQuery)
Do Until myRecordset.EOF
For Each fld In myRecordset.Fields
Debug.Print fld.Name & "=" & fld.Value
Next fld
myRecordset.MoveNext
Loop
myRecordset.Close
Set myRecordset = Nothing
ConnDB.Close
Set ConnDB = Nothing
End Function
Actual output from access is "18" which is expected, output from excel's vba recordset is always null or empty string.
It appears I solved the problem, while looking into this apparently the excel operator using ADODB with access is % for LIKE and NOT * (because reasons). As soon as I made that change everything started working.
Can someone explain why that is a thing? I really want to understand why this was a design choice.
First time asker, usually I can find the answer by searching, but my google-fu seems weak today.
I have an excel workbook connecting to an access 2003 database to insert usage records
The code i'm using is:
sdbpath = ThisWorkbook.Path & "\Data.mdb"
sCommand = "INSERT INTO Usage VALUES('" & Environ("Username") & "',#" & Now() & "#)"
Dim dbCon As New ADODB.Connection
Dim dbCommand As New ADODB.Command
dbCon.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sdbpath & "; Jet OLEDB:Database Password=TestPass;"
dbCommand.ActiveConnection = dbCon
dbCommand.CommandText = sCommand
dbCommand.Execute
dbCon.Close
The code fails on the line dbCommand.Execute with run-time error '-2147217900 (80040e14)' : Automation error.
The database its trying to insert the record into contains one table, usage, with two columns - UserID and AccessDate, formatted as text and DateTime respectively.
The odd part is the connection string seems OK, since it fails after the connection is already open, yet if I take the sCommand value before the execute is run, then paste it into a query in access and execute that - it runs fine!
In case it was access struggling with the datetime format i've tried switching it to text (and the hashtags in the code) but that still fails. I've also tried specifying the column names too.
Can anyone shed some light on what i'm doing wrong? I've never had so much trouble with a very simple bit of SQL.
Thanks in advance!
In Access we need to specify the field-names. Even so, I found that I needed to wrap the table-name in square brackets before it would insert:
sCommand = "INSERT INTO [Usage] (UName, SomeDate) VALUES ('" & Environ("Username") _
& "',#" & Now() & "#)"
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