I've written a simple form handler script using ASP3.0/VBScript and would like to add the inputted data (via the web) to an Access database located on my server. I'm using the OLEDB method to connect like so:
Cst = "PROVIDER=Microsoft.Jet.OLEDB.4.0;" & _
"DATA SOURCE=" & Server.MapPath("DataBase.mdb")
Dim Conn
Set Conn = CreateObject("ADODB.Connection")
Conn.Mode = 3
Conn.Open Cst
Blah Blah Blah...
I currently have a file named ADOVBS.inc included at the top but would like to ditch it because I feel it's inefficient and wasteful. I'd like to define the constants as I need them- but I don't know how. What ADO constants would I need to define and where? The book that I'm using basically says "forget about that- pound include those 400 or so boogers in there and don't ask stupid questions!"
Any specific examples/help would be greatly appreciated.
Thanks,
you have a couple of options to choose from. You can reference the metadata library in your page ( or in your global.asa file ) with
<!--
METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"
-->
or
you can simply copy a few constants from the adovbs file into your page to cover your needs. For example
Const adCmdText = 1 'Evaluate as a textual definition
Const adCmdStoredProc = 4 'Evaluate as a stored procedure
Of course that the answer is "Forget about that- pound include those 400 or so boogers in there and don't ask stupid questions!" :)
But since you insist:
The best way is to encapsulate all data access function in one .ASP
Let's call it dbHelper.asp
Then put all the DB functions in there, like:
''// run a query and returns a disconnected recordset
Function RunSQLReturnRS(sqlstmt, params())
On Error Resume next
''//Create the ADO objects
Dim rs , cmd
Set rs = server.createobject("ADODB.Recordset")
Set cmd = server.createobject("ADODB.Command")
''// Init the ADO objects & the stored proc parameters
cmd.ActiveConnection = GetConnectionString()
cmd.CommandText = sqlstmt
cmd.CommandType = adCmdText
collectParams cmd, params
''//Execute the query for readonly
rs.CursorLocation = adUseClient
rs.Open cmd, , adOpenForwardOnly, adLockReadOnly
If err.number > 0 then
BuildErrorMessage()
exit function
end if
''//Disconnect the recordset
Set cmd.ActiveConnection = Nothing
Set cmd = Nothing
Set rs.ActiveConnection = Nothing
''//Return the resultant recordset
Set RunSQLReturnRS = rs
End Function
At that point, you know that all you ado constants are in this file and you can start replacing them as wished.
Relevant list of constants can be found here: https://web.archive.org/web/20190225142339/http://www.4guysfromrolla.com:80/ASPScripts/PrintPage.asp?REF=/webtech/faq/beginner/faq7.shtml
I'll copy it here as well:
'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3
'---- CursorOptionEnum Values ----
Const adHoldRecords = &H00000100
Const adMovePrevious = &H00000200
Const adAddNew = &H01000400
Const adDelete = &H01000800
Const adUpdate = &H01008000
Const adBookmark = &H00002000
Const adApproxPosition = &H00004000
Const adUpdateBatch = &H00010000
Const adResync = &H00020000
Should be enough for inserting/selecting/updating records in database.
Related
I am newbie in VBScript and I've come across with the following problem. I want get data from sql server db and to allow RecordCount properties. Next code get data but RecordCount is disabled. How can I enable this properties
Const DB_CONNECT_STRING = "Provider=SQLOLEDB.1;Data Source=BUG\SQLSERVER2005;Initial Catalog=test;user id ='sa';password='111111'"
Set myConn = CreateObject("ADODB.Connection")
Set myCommand = CreateObject("ADODB.Command" )
myConn.Open DB_CONNECT_STRING
Set myCommand.ActiveConnection = myConn
myCommand.CommandText = ("select * from klienci k where k.indeks = " & oferty(16))
Set klienci = myCommand.Execute
AFAIK you can't change the cursor type when using the Execute method of the Command object, and you can't change the cursor type after you retrieved the recordset. Something like this might work, though:
Const DB_CONNECT_STRING = "Provider=SQLOLEDB.1;Data Source=BUG\SQLSERVER2005;Initial Catalog=test;user id ='sa';password='111111'"
Set myConn = CreateObject("ADODB.Connection")
myConn.Open DB_CONNECT_STRING
query = "select * from klienci k where k.indeks = " & oferty(16)
Set klienci = CreateObject("ADODB.Recordset")
klienci.CursorLocation = 3 'adUseClient
klienci.CursorType = 3 'adOpenStatic
klienci.LockType = 1 'adLockReadOnly
klienci.Open query, myConn
I don't think this is a VBScript issue- I think it is an ADO issue.
I think you are using a default forward-only cursor which won't work with recordcount.
I think you should stick a cursortype=adOpenStatic in there but I'm having a little trouble determining if you are specifying a recordset object - klienci?
If so try
klienci.cursortype=adOpenStatic
I have a query called qryAlloc_Source that has two paramaters under one criteria:
>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
A have a separate query that ultimately references qryAlloc_Source (there are a couple queries in between), and that query runs fine when I double click it in the UI, but if I try to open it in VBA, I get an error. My code is:
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
I am getting run-time error 3061, Too few parameters. Expected 2. I've read that I may need to build out the SQL in VBA using the form parameters, but it would be pretty complex SQL given that there are a few queries in the chain.
Any suggestions as to a workaround? I considered using VBA to create a table from the query and then just referencing that table--I hate to make extra steps though.
The reason you get the error when you just try to open the recordset is that your form is not open and when you try to access [forms]![frmReportingMain] it's null then you try to get a property on that null reference and things blow up. The OpenRecordset function has no way of poping up a dialog box to prompt for user inputs like the UI does if it gets this error.
You can change your query to use parameters that are not bound to a form
yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
Then you can use this function to get the recordset of that query.
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim db As DAO.Database
Dim qdef As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs("qryAlloc_Debits")
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
The disadvantage to this is that when you call this now on a form that is bound to it it doesn't dynamically 'fill in the blanks' for you.
In that case you can bind forms qryAlloc_debts and have no where clause on the saved query, then use the forms Filter to make your where clause. In that instance you can use your where clause exactly how you have it written.
Then if you want to still open a recordset you can do it like this
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim qdef As DAO.QueryDef
Set qdef = New DAO.QueryDef
qdef.SQL = "Select * from qryAlloc_Debits where AllocStart >= pAllocStart and pAllocEnd <= pAllocEnd"
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
While a [Forms]!... reference does default to a form reference when a QueryDef is run from the GUI, it is actually just another Parameter in the query in VBA. The upshot is you don't have to recode your query/create a new one at all. Also, as #Brad mentioned, whether a parameter is in the final query of a chain of queries or not, you are able to refer to the parameter as if it is in the collection of the final query. That being the case, you should be able to use code similar to this:
Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryAlloc_Debit")
If CurrentProject.AllForms("frmReportingMain").IsLoaded Then
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart]
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd]
Else
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart)
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd)
End If
Set rst = qdf.OpenRecordset
Do Until rst.EOF
'...do stuff here.
Loop
Set rst = Nothing
Set qdf = Nothing
Set db = Nothing
End Function
If the referenced form is open, the code is smart enough to use the referenced controls on the form. If not, it will use the dates supplied to the subroutine as parameters. A gotcha here is that the parameters did not like when I set them as date types (#xx/xx/xx#), even if the field were dates. It only seemed to work properly if I set the params as strings. It didn't seem to be an issue when pulling the values straight out of the controls on the forms, though.
I know it's been a while since this was posted, but I'd like to throw in my tuppence worth as I'm always searching this problem:
A stored query can be resolved:
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
For SQL:
Set db = CurrentDb
Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " & _
"WHERE ID = " & Me.lstID & _
" AND dWeekCommencing = " & CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) & _
" AND DB_Status = 'Used'")
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
This assumes that all parameter values are accessible - i.e. forms are open and controls have values.
'I have two parameters in my recordset and I was getting the "Too few parameters. Expected 2" 'error when using an OpenRecordset in MS Access vba, and this is how I got around it and IT WORKS! see the below sub routine:
'Private Sub DisplayID_Click()
'1. I created variables for my two parameter fields xEventID and xExID as seen below:
Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer
Dim xExId As Integer
'2. Sets the variables to the parameter fields as seen below:
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
'3. Set the rst to OpenRecordSet and assign the Set the variables to the WHERE clause. Be sure to include all quotations, ampersand, and spaces exactly the way it is displayed. Otherwise the code will break!exactly as it is seen below:
Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _
& "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _
& "WHERE (((tblInfo_Exhibitor.EventID) =" & xEventID & " ) and ((tblInfo_Exhibitor.ExID) =" & xExId & " ));")
rst.Close
Set rst = Nothing
db.Close
'End Sub
I have the following stored procedure:
alter proc SPCP_ProgramUpdate
#ID int,
#UserID int,
#Name nvarchar(150),
#University int,
#Level tinyint,
#isActive bit
as
update tblUniversityProgram set University_Fkey = #University, Level_Fkey = #Level, Program_Name = #Name, EditDate = GETDATE(), EditUser = #UserID, isActive = #isActive
where tblUniversityProgram.ID = #ID
When I run the stored procedure from SSMS, it works as intended.
However, when I run that stored procedure from ASP.NET using this code:
Dim varDbconn As New SqlConnection
Dim varDbcomm As SqlCommand
Dim varDbRead As SqlDataReader
varDbconn.ConnectionString = ConfigurationManager.ConnectionStrings("CPDB_ConnectionString").ToString
varDbconn.Open()
If Request.QueryString("program") <> "" Then
varDbcomm = New SqlCommand("SPCP_ProgramUpdate", varDbconn)
varDbcomm.CommandType = CommandType.StoredProcedure
varDbcomm.Parameters.AddWithValue("#ID", Request.QueryString("program")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#UserID", Session("UserID")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#University", Session("DecryptID")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#Level", ddlLevel.SelectedValue).DbType = DbType.Byte
varDbcomm.Parameters.AddWithValue("#isActive", chkisActive.Checked).DbType = DbType.Boolean
varDbcomm.Parameters.AddWithValue("#Name", txttitle.Text).DbType = DbType.String
varDbcomm.ExecuteNonQuery()
varDbcomm.Dispose()
Else
....
End IF
varDbconn.Close()
nothing happens.
Any ideas?
The most likely answer to your question is that the value you are getting out of the querystring for program is not the Id in your database that you expect.
At the minute, your code is reading in input values and passing them to a stored procedure without any validation of your expected values - missing session for example could cause you all sorts of unexpected issues.
Debug your code and see exactly what parameters you are passing to your DB. Check your connection string to see that you are hitting the database where you have amended your stored procedure.
What you have should work. I would use parmaters.Add in place of addwith, but that should not really matter.
Try adding this code right after you are done setting up the parmaters:
Debug.Print("SQL = " & varDbcomm.CommandText)
For Each p As SqlParameter In varDbcomm.Parameters
Debug.Print(p.ParameterName & "->" & p.Value)
Next
That way in the debug window (or immediate depending on VS settings), you see a list of param values, and the parameter names. I suspect one of the session() values is messed up here.
I am trying to make a Classic ASP/VBScript website more secure by making SQL statements parameterized.
I have the following function:
Function OpenUpdateableRS(strSQL)
Dim rs
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open strSQL, cnDZ, adOpenKeyset, adLockPessimistic, adCmdText
Set OpenUpdateableRS = rs
Set rs = Nothing
End Function
I intend to convert it to something like:
Function SecureOpenUpdateableRS(strSQL, strParam1, strParam2)
Dim rs
Dim cmdOB
Set cmdOB = Server.CreateObject("ADODB.CommandObject")
With cmdOB
.ActiveConnection = cnDZ
.CommandText = strSQL
.Parameters(0).value = strParam1
.Parameters(0).value = strParam2
End With
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open cmdOB.Execute, , adOpenKeyset, adLockPessimistic
Set SecureOpenUpdateableRS = rs
Set rs = Nothing
End Function
When I call the function with:
Set rs = SecureOpenUpdateableRS("SELECT CustID, LastActive, LoggedIn, SessionID FROM tblLogins WHERE EMail = ? AND PWord = ?", strEMail, strPassword)
I get a "500 - Internal Server Error" which is probably because I disabled debugging on the server.
Any ideas on how I could make the original function more secure without breaking it?
You'll have to create the parameters and append them to the command's parameter collection. Just assigning the values to (the same!) parameter can't possibly work. Google for a sample; perhaps this VB! sample will get you started.
Added:
I can think of two strategies to derive the parameter types:
If you pass the correct/maximally specified parameter values to the function you can map VarType(value) constants to parameter type constants
If you do a SELECT based on the fieldnames in the command text, you can map the recordset's field .Types to parameter type constants
It won't be trivial to get this right for all possible cases. I would pass pairs of value and desired type to the function.
I'm trying to write a parameterized query in ASP Classic, and it's starting to feel like i'm beating my head against a wall. I'm getting the following error:
Must declare the scalar variable "#something".
I would swear that is what the hello line does, but maybe i'm missing something...
<% OPTION EXPLICIT %>
<!-- #include file="../common/adovbs.inc" -->
<%
Response.Buffer=false
dim conn,connectionString,cmd,sql,rs,parm
connectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Data Source=.\sqlexpress;Initial Catalog=stuff"
set conn = server.CreateObject("adodb.connection")
conn.Open(connectionString)
set cmd = server.CreateObject("adodb.command")
set cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.CommandText = "select #something"
cmd.NamedParameters = true
cmd.Prepared = true
set parm = cmd.CreateParameter("#something",advarchar,adParamInput,255,"Hello")
call cmd.Parameters.append(parm)
set rs = cmd.Execute
if not rs.eof then
Response.Write rs(0)
end if
%>
Here's some sample code from an MSDN Library article on preventing SQL injection attacks. I cannot find the original URL, but googling the title keywords (Preventing SQL Injections in ASP) should get you there quick enough. Hope this real-world example helps.
strCmd = "select title, description from books where author_name = ?"
Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set param1 = objCommand.CreateParameter ("author", adWChar, adParamInput, 50)
param1.value = strAuthor
objCommand.Parameters.Append param1
Set objRS = objCommand.Execute()
See the following page on MSDN, near the bottom, referring specifically to named parameters.
MSDN example
ADO is going to expect question marks instead of actual parameter names in this case. Right now, the SQL "select #something" is not actually parameterized: it sees the "#something" as an (undeclared) SQL variable, not as a parameter. Change your CommandText line to this:
cmd.CommandText = "select ?"
And I think you will get the result you are looking for.
Good luck!
with server.createobject("adodb.command")
.activeConnection = application("connection_string")
.commandText = "update sometable set some_col=? where id=?"
.execute , array(some_value, the_id)
end with
I'm not sure what your query is intended to accomplish. I'm also not sure that parameters are allowed in the select list. MSDN used to have (many years ago, probably) a decent article on where parameters were allowed in a query, but I can't seem to find it now.
OTTOMH, your attempts to supply the parameter values to ADO look correct. Does your query execute if you do something like this?
SELECT 1 FROM sometable WHERE somefield = #something