I am having trouble when I try to introduce alphanumeric characters into ms-access database. I am able to do it with numerical and date characters, but it seems to be a problem with alphanumerical ones,
Here is the code I use:
Dim adoCon
Dim strSQL
Set adoCon=Server.CreateObject("ADODB.Connection")
adoCon.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Server.MapPath("basededades.mdb")
'Here I am getting all the values previously passed by a form.
stringEntrada=Request.Form("stringEntrada")
stringSortida=Request.Form("stringSortida")
valoridHabitaciolliure=Request.Form("valoridHabitaciolliure")
numeropersones=Request.Form("numeroPersones")
nom=Request.Form("nom")
dni=Request.Form("dni")
tlf=Request.Form("tlf")
mail=Request.Form("mail")
ciutat=Request.Form("ciutat")
tipusH=Request.Form("tipusH")
diaReserva=Request.Form("diaReserva")
mail,nom,ciutat,tipusH,dni,valoridHabitaciolliure are alphanumerical characters from a text input form.
diaReserva,stringSortida,stringEntrada, are dates form a text input form.
tlf is a integer variable.
strSQL="INSERT INTO Reserva (dni,tlf,diaReserva,inici,fi,tipusHabitacio) VALUES ("&dni&","&tlf&",'"&diaReserva&"','"&stringEntrada&"','"&stringSortida&"'," "&tipusH&")"
adoCon.Execute(strSQL)
When I see the values inserted into the database I realise that the date variables like "diaReserva" or "stringSortida" and the numerical ones like "tlf" are inserted correctly.
To insert date variables I use a simple ' surrounded by double " in the sql query: '"&stringEntrada&"'
To insert numerical ones I only use the double: "&tlf&"
If I try to use simple ' when I am trying to insert an alphanumerical, like: '"mail"' I do not recieve any error, but the database records a blank value.
If I try to use double ", like: "mail" I am getting an error.
How I could insert alphanumerical variables without having trouble?
Thank you for your time, and sorry for my bad english.
You can avoid your "quoting problem" and also avoid SQL Injection vulnerabilities by using a parameterized query similar to this one:
Dim con '' As ADODB.Connection
Dim cmd '' As ADODB.Command
Dim stringName, longSponsorID, datetimeDateJoined
Const adCmdText = 1
Const adVarWChar = 202, adInteger = 3, adDate = 7
Const adParamInput = 1
'' test data
stringName = "Gord"
longSponsorID = 5
datetimeDateJoined = Now
Set con = CreateObject("ADODB.Connection")
con.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Public\mdbTest.mdb;"
Set cmd = CreateObject("ADODB.Command")
cmd.CommandType = adCmdText
cmd.ActiveConnection = con
cmd.CommandText = _
"INSERT INTO Members " & _
"(memberName, sponsorID, dateJoined) " & _
"VALUES " & _
"(?, ?, ?)"
'' parameter for [memberName]
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, stringName)
'' parameter for [sponsorID]
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput, , longSponsorID)
'' parameter for [dateJoined]
cmd.Parameters.Append cmd.CreateParameter("?", adDate, adParamInput, , datetimeDateJoined)
cmd.Execute
Set cmd = Nothing
con.Close
Set con = Nothing
Related
OK, I'm missing something obvious here - I have an SP that takes in an integer ID and returns a string. I've used this SP for quite a while with DAO. Now I need to switch to ADO so I can run it under and existing connection (another question I'll post elsewhere).
So my code follows. It returns no errors but it also returns no results. The output parameter is null. What am I missing?
Dim adoCon As ADODB.Connection
Dim adoCMD As ADODB.Command
Dim SQLstr As String
Dim ConStr As String
'--- get connection string from existing object, but strip leading odbc; piece
ConStr = Replace(CurrentDb.TableDefs("[TableName]").Connect, "ODBC;", "")
Set adoCon = New ADODB.Connection
adoCon.ConnectionString = ConStr
adoCon.Open
Set adoCMD = New ADODB.Command
With adoCMD
.ActiveConnection = adoCon
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter(, adInteger, adParamReturnValue, , Null) ' return value
.Parameters.Append .CreateParameter("Path", adVarChar, adParamOutput, 500, Null)
.Parameters.Append .CreateParameter("AsyID", adInteger, adParamInput)
.Parameters.Item("AsyID").Value = AsyID
.CommandText = "dbo.spGetAncestry"
.Execute
End With
GetHeritage = adoCMD.Parameters(1).Value 'parm(0) = 0; parm(1) = NULL; parm(2) = AsyID
adoCon.Close
Although your code should work. Please remove the optional expressions in the parameter definition and try the following:
Dim rv as Integer
Set adoCMD = New ADODB.Command
With adoCMD
.ActiveConnection = adoCon
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("RETURN_VALUE", adInteger, adParamReturnValue)
.Parameters.Append .CreateParameter("Path", adVarChar, adParamOutput, 500)
.Parameters.Append .CreateParameter("AsyID", adInteger, adParamInput, , AsyID)
.CommandText = "dbo.spGetAncestry"
.Execute
End With
rv = adoCMD.Parameters("RETURN_VALUE").Value
GetHeritage = adoCMD.Parameters("Path").Value
also make sure your SP is returning the correct data type and size for your output parameter and adjust the code accordingly. If you're returning VARCHAR(MAX), then that is treated as a "BLOB" in ADO, see this related question What are the limits for ADO data types?.
In this case you can try returning varchar(8000) from the SP and updating the code accordingly.
Found it.
Apparently, in the ADO call, it doesn't matter what you set the return value to (I was trying to use "" or even " " before I set it to null) when it executes in SQL batch, it is simply set to NULL as it shows in this trace form. For this run, the Output was initialized as " ", but the batch passed in NULL.
[!SQL trace of the above query being executed with " " in the initialization of the Output variable1]1
Normally, a null wouldn't be a problem as the typical SP assignment would be:
SET #Path = [SELECT value from table]
or, if it was a concatenation, you would initialize the variable:
SET #Path = ''
before stringing together the input.
In this particular case, though, the SP is recursive. It calls itself passing an input and the output values to the new copy. Because of this, you can't initialize the value and you can't use a straight assignment. To get around this, I needed to use:
#path = COALESCE(#path, '') + [SELECT value from table]
to trap any NULL passed in.
I'm trying to use the parameterizartion to prevent SQL injection in one of the textbox in the HMI I working with.
Have looked a lot for a solution what I gathered is depending on what SQL syntax there is I can use either ? or # to tell the system that is parameter but both of them are throwing an error.
Dim DBCommand
Dim DBRecordSet
Dim Connection
Dim sqlString
Set DBRecordSet = CreateObject("ADODB.Recordset")
Set DBCommand = CreateObject("ADODB.Command")
Set Connection = GetDBConnection("Test")
sqlString = "Insert into [WorkCommentLog] (Worklog_WorkID, Comment,
InsertTime, WrittenBy) values" &_
"('"& WorkID &"' , #Comm , GetDate() , '" & User.Value &"');"
DBCommand.Parameters.Append DBCommand.CreateParameter ("#Comm",
adVarChar, adParamInput, 255, WinCC_Comment.Value)
DBCommand.CommandText = sqlString
DBCommand.Execute(adExecuteNoRecords)
Connection.Close
Dim DBCommand
Dim DBRecordSet
Dim Connection
Dim sqlString
Set DBRecordSet = CreateObject("ADODB.Recordset")
Set DBCommand = CreateObject("ADODB.Command")
Set Connection = GetDBConnection("Test")
sqlString = "Insert into [WorkCommentLog] (Worklog_WorkID, Comment, InsertTime, WrittenBy) values" &_
"('"& WorkID &"' , ? , GetDate() , '" & User.Value &"');"
DBCommand.Parameters.Append DBCommand.CreateParameter ("Comment", adVarChar, adParamInput, 255, WinCC_Comment.Value)
DBCommand.CommandText = sqlString
DBCommand.Execute(adExecuteNoRecords)
Connection.Close
The first code snippet throws this error:
Must declare the scalar variable "#Com"
while the second code snippet throws this error:
No Value given for one or more required parameters
I have found that executing a parametrized query using VBScript like so has always worked for me:
Set command = CreateObject("ADODB.Command")
Set command.ActiveConnection = Connection
command.CommandText = "sp0001_ExampleStoredProcedure" ' The name of the stored procedure in my database that has the parametrized query.
command.CommandType = 4
command.Parameters("#Parameter1") = "parameterValue"
command.Parameters("#Parameter2") = "parameterValue"
command.Execute
Note that this example is executing a parametrized stored procedure in my database.
You could try writing your insert query into a stored procedure in your database instead of hard-coding your query in the VBScript file.
I'm working in ACCESS VBA. I have a sub, which inserting the given collection into different tables, which depends on the current element. I just met and would like to work with this ADO parameter thing, because I have problem with the simple docmd.runsql "insert into...". The problem is that some strings contain "'" character, so I got error at these records. I searched and found ADO parameters, but no good tutorials and now I'm tired from the error codes which are not helpful either (coming from java).
My code snippet:
Dim adoCMD As Object
Set adoCMD = CreateObject("ADODB.Command")
With adoCMD
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdText
.parameters.Append .CreateParameter("pKey", adInteger)
.parameters.Append .CreateParameter("pTitle", adVarChar, 100)
.parameters.Append .CreateParameter("pid", adInteger)
.parameters.Append .CreateParameter("pAired", adDate)
.parameters.Append .CreateParameter("pmtype", adInteger)
.parameters.Append .CreateParameter("pSyear", adSmallInt)
.parameters.Append .CreateParameter("pSeason", adInteger)
If addDate Then
.parameters.Append .CreateParameter("pAdded", adDate)
End If
For Each elem In ac
If elem.aired >= seasonStart And elem.aired <= seasonEnd Then
key = Nz(DMax("table_Akey", "table_A"), 0) + 1
.parameters("pKey").Value = key
.parameters("pTitle").Value = elem.title
.parameters("pid").Value = elem.id
.parameters("pAired").Value = elem.aired
.parameters("pmtype").Value = elem.mtype
.parameters("pSyear").Value = syear
.parameters("pSeason").Value = season
If addDate Then
.parameters("pAdded").Value = Date
.CommandText = "INSERT INTO table_A(table_Akey,title,id,aired,media,seasonyear,season,added) VALUES(pKey,pTitle,pid,pAired,pmtype,pSyear,pSeason,pAdded);"
Else
.CommandText = "INSERT INTO table_A(table_Akey,title,id,aired,media,seasonyear,season) VALUES(pKey,pTitle,pid,pAired,pmtype,pSyear,pSeason);"
End If
Else
wCounter = wCounter + 1
key = Nz(DMax("wskey", "ws"), 0) + 1
.parameters("pKey").Value = key
.parameters("pTitle").Value = elem.title
.parameters("pid").Value = elem.id
.parameters("pAired").Value = elem.aired
.parameters("pmtype").Value = elem.mtype
.parameters("pSyear").Value = syear
.parameters("pSeason").Value = season
.CommandText = "INSERT INTO ws(wskey,title,id,aired,media,wsyear,season) VALUES(pKey,pTitle,pid,pAired,pmtype,pSyear,pSeason);"
End If
.Execute
Next elem
End With
I get the error: Runtime Error '3001' Arguments are of the wrong type, are out of acceptable range or are in conflict with one another
at the line
.parameters.Append .CreateParameter("pTitle", adVarChar, 100)
Maybe the whole code is wrong, I don't know how to do properly with ADO parameters, but you can see what I want to do. I give a collection to the function. I loop through the elements and place them the right table and I have one switch as well (addDae).
Please help me.
You could also write a function that escapes the DB single quote. Generally, a single quote is "escaped" by doubling it. It would be something like:
Function escapeDBquote(s As String) As String
Dim sOut As String
Dim i As Integer
i = 1
While (i <= len(s))
If (Mid(s, i, 1) = "'") Then sOut = sOut +"'"
sOut = sOut + Mid(s, i, 1)
i = i + 1
Wend
escapeDBquote = sOut
End Function
and call it like:
Dim szSQL As String
szSQL = "insert into myTable (sfield1, ..) values ('" + escapeDBquote(myString) + "');"
(Note: haven't compiled this code; there could be some typos.)
I have a database and MSSQL code in vbscript:
Dim conn, SQL, rs
Const DB_CONNECT_STRING = "Provider=SQLOLEDB.1;Data Source=DJ-PC;Initial Catalog=Baza_NC;user id ='user_baza_nc';password='Password1'"
Set myConn = CreateObject("ADODB.Connection")
Set myCommand = CreateObject("ADODB.Command" )
myConn.Open DB_CONNECT_STRING
Set myCommand.ActiveConnection = myConn
myCommand.CommandText = "UPDATE Klienci_NC SET Klienci_NC.Klient = '" & Klient_niceform & "' WHERE Klienci_NC.ID = '" & ID_zmienna & "'"
myCommand.Execute
myConn.Close
When I use the ID with the participation of a txt file as a counter to work well.
The problem appeared when I wanted to use the MSSQL database autoincremant.
I need a string variable to the variable & ID_zmienna &
How to get a string variable with the ID field from the database?
Not sure why you are trying to call an INT data type in SQL as a VARCHAR.
The query should be
myCommand.CommandText = "UPDATE Klienci_NC SET Klienci_NC.Klient = '" & Klient_niceform & "' WHERE Klienci_NC.ID = " & ID_zmienna
you only pass ' for string data types in SQL Server, integers are just
[column] = int_value
Having said all that you should be passing the parameters in the .Parameters collection of the ADODB.Command object rather than specifying them directly in the SQL query string. As it stands the page is open to SQL Injection attack and also means you have to handle not passing ' when dealing with INT and escaping extra ' in strings etc., which just isn't necessary.
Dim SQL, myCommand
Const DB_CONNECT_STRING = "Provider=SQLOLEDB.1;Data Source=DJ-PC;Initial Catalog=Baza_NC;user id=user_baza_nc;password=Password1"
'Most ADO providers expect a `?` to denote where a parameter is expected.
SQL = "UPDATE Klienci_NC SET Klienci_NC.Klient = ? WHERE Klienci_NC.ID = ?"
Set myCommand = CreateObject("ADODB.Command" )
With myCommand
'No need for ADODB.Connection object ADODB.Command can create one from the
'Connection String.
.ActiveConnection = DB_CONNECT_STRING
.CommandType = adCmdText
.CommandText = SQL
'Define parameters in order they appear in the query.
Call .Parameters.Append(.CreateParameter("#klient", adVarWChar, adParamInput, 50))
Call .Parameters.Append(.CreateParameter("#id", adInteger, adParamInput, 4))
'Only running an update statement so no need to return a
'ADODB.Recordset.
Call .Execute(, Array(Klient_niceform, ID_zmienna), adExecuteNoRecords)
End With
'Release the object from memory
Set myCommand = Nothing
Useful Links
Assuming you are using Classic ASP with VBScript
Using METADATA to Import DLL Constants (if you are having problems with the ADO constants like adCmdText, adInteger etc., being undefined this will help)
Otherwise you will need to define the ADO constants yourself like so;
Const adCmdText = 1
Const adInteger = 3
Const adVarWChar = 202
Const adParamInput = 1
Const adExecuteNoRecords = &H00000080
I need to insert some data into DB, there is a problem..it gives me an error :
Source line:
SET sql ="Insert Into Products (ProductName,SupID,CatID,Price,Pic,Description) Values( '"&pName&"','"&pbId&"','"&pcId&"','"&price&"','"&pic&"','"&desc&"')"
Description: Object required: '[string: "Insert Into Products"]'
I dont understand what he wants..
This is my code:
dim sql
dim price
dim desc
dim pName
dim pcId
dim pbId
dim pic
set pic = Request.Form("picUpload")
set desc = Request.Form("tbDescProduct")
set price= Request.Form("tbPriceProduct")
set pcId =Request.Form("ddlCategoryForProd")
set pbId =Request.Form("ddlBrandForProd")
set pName=Request.Form("tbProductName")
IF((bName<>"")AND(desc<>"")AND(price<>"")AND(pcId<>"-1")AND(pbId<>"-1")AND (pic<>"")) THEN
set con = Server.CreateObject("ADODB.Connection")
con.open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("WebData/DB.mdb") & ";"
set rs = con.Execute("Select * FROM Products WHERE ProductName = '"&pName&"' and mode= true")
IF rs.EOF = true then
SET sql ="Insert Into Products (ProductName,SupID,CatID,Price,Pic,Description) Values( '"&pName&"','"&pbId&"','"&pcId&"','"&price&"','"&pic&"','"&desc&"')"
SET rs =con.Execute(sql)
response.write("<script language=""javascript"">alert('Product added succesfully!');</script>")
ELSE
response.write("<script language=""javascript"">alert('Product already exist!');</script>")
END IF
'END IF
In VBScript, VBA and VB5/6, SET is required to assign an object reference; to assign any other sort of data (including a string), just remove it:
sql = "Insert Into Products (ProductName,SupID,CatID,Price,Pic,Description) Values( '"&pName&"','"&pbId&"','"&pcId&"','"&price&"','"&pic&"','"&desc&"')"
(In VBA and VB5/6 you could also use LET here.)
The reason SET works when assigning the result of a Request.Form("foo") call is because the Form collection is a collection of objects - the subsequent tests against "" and "-1" are valid only because the objects returned have a default parameterless property or method that return a string-compatible variant.
If I was to guess I'd say your problem is you're passing the SupID and CatID fields as strings when they are probably integers. The problem with handling INSERT this way is you leave yourself open to SQL Injection plus you encounter data type issues like you seem to be experiencing here.
Whenever possible when interacting with a database you should try to use Parameterised Queries. In Classic ASP the best object to do this is ADODB.Command.
Here is an example using your code;
NOTE: If you have problems with the ADO named constants like adParamInput then look in the links section below to see how to use the METADATA tag in your global.asa file to reference the ADO type library across your application.
Dim cmd, sql, conn_string, rs, data
'Wouldn't recommend storing your database inside your website root, instead
'store it outside in another folder and set up a variable in an include file
'to store the location. That way it is not accessible to everyone.
conn_string = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("WebData/DB.mdb") & ";"
Set cmd = Server.CreateObject("ADODB.Command")
sql = "SELECT * FROM Products WHERE ProductName = ?"
With cmd
.ActiveConnection = conn_string
.CommandType = adCmdText
.CommandText = sql
Call .Parameters.Append(.CreateParameter("#ProductName", adVarWChar, adParamInput, 50))
Set rs = .Execute(, Array(pName))
If Not rs.EOF Then data = rs.GetRows()
Call rs.Close()
Set rs = Nothing
End With
If IsArray(data) Then
sql = ""
sql = sql & "INSERT INTO Products (ProductName, SupID, CatID, Price, Pic, Description) " & vbCrLf
sql = sql & "VALUES (?, ?, ?, ?, ?, ?)"
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn_string
.CommandType = adCmdText
.CommandText = sql
'Define Parameters
'Making some assumptions about your data types, but you can modify these to fit
'good guide for this is http://www.carlprothman.net/Technology/DataTypeMapping/tabid/97/Default.aspx
Call .Parameters.Append(.CreateParameter("#ProductName", adVarWChar, adParamInput, 50))
Call .Parameters.Append(.CreateParameter("#SupID", adInteger, adParamInput, 4))
Call .Parameters.Append(.CreateParameter("#CatID", adInteger, adParamInput, 4))
Call .Parameters.Append(.CreateParameter("#Price", adCurrency, adParamInput, 4))
Call .Parameters.Append(.CreateParameter("#Pic", adVarWChar, adParamInput, 255))
Call .Parameters.Append(.CreateParameter("#Description", adLongVarWChar, adParamInput, 1000))
'Some of your variables may require conversion before setting the parameter values.
.Parameters("#ProductName").Value = pName
.Parameters("#SupID").Value = CLng(pbId)
.Parameters("#CatID").Value = CLng(pcId)
.Parameters("#Price").Value = price
.Parameters("#Pic").Value = pic
.Parameters("#Description").Value = desc
'Execute Command
.Execute()
End With
Set cmd = Nothing
Call Response.write("<script language=""javascript"">alert('Product added succesfully!');</script>")
Else
Call Response.Write("<script language=""javascript"">alert('Product already exist!');</script>")
End If
Links
Data Type Mapping
Using METADATA to Import DLL Constants
Answer from SQL insert into database with apostrophe