OK, I am trying to write a Classic ASP function that will call a SQL function and return the output.
I am trying to use a paramaterized ADODB connection but I don't quite know how these work. Trying to learn the correct way.
The SQL function just takes two string input where one is a "salt" and the other the actual text and turnes it into a hex.
Works fine in SQL but I just can not get it to work through classic ASP.
I keep getting,
ADODB.Command error '800a0cc1'
Item cannot be found in the collection corresponding to the requested name or ordinal.
Sub Encrypt(plainString)
strSQL = "SET NOCOUNT ON;SELECT dbo.Encrypt('xx', '?') as keycode"
Set cnnEncrypt = Server.CreateObject("ADODB.Connection")
cnnEncrypt.open CONNSTRING
Dim cmd1
Set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = cnnEncrypt
cmd1.CommandText = strSQL
cmd1.CommandType = adCmdText
cmd1.Parameters(0) = plainString (**Original Error Occured Here!!!!**)
Set rsEncrypt = cmd1.Execute()
If not rsEncrypt.EOF Then
Encrypt = rsEncrypt.Fields("keycode").Value
Else
Encrypt = "blank"
End If
' Clean Up
rsEncrypt.Close
Set rsEncrypt = Nothing
cnnEncrypt.Close
Set cnnEncrypt = Nothing
End Sub
New Working Version after reviewing "Cheran Shunmugavel" answer.
Calling on site like this
< % Response.Write Decrypt(Encrypt("test")) % >
You can't print the Encrypted code to the page because it is Binary. You would need a Binary to String function.
I converted from Sub to Function because I wanted the function to return a value.
Function Encrypt(byVal plainString)
strSQL = "SET NOCOUNT ON;SELECT dbo.Encrypt('xx', ?) as keycode"
Set cnnEncrypt = Server.CreateObject("ADODB.Connection")
cnnEncrypt.open CONNSTRING
Dim cmd1
Set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = cnnEncrypt
cmd1.CommandText = strSQL
cmd1.CommandType = adCmdText
cmd1.Parameters.Append cmd1.CreateParameter("", adVarChar, adParamInput, Len(plainString)+1, plainString)
Set rsEncrypt = cmd1.Execute()
If not rsEncrypt.EOF Then
Encrypt = rsEncrypt.Fields("keycode").Value
Else
Encrypt = "blank"
End If
' Clean Up
rsEncrypt.Close
Set rsEncrypt = Nothing
cnnEncrypt.Close
Set cnnEncrypt = Nothing
End Function
And here is the decrypt function.
Function Decrypt(byVal plainString)
strSQL = "SET NOCOUNT ON;SELECT dbo.Decrypt('xx', ?) as keycode"
Set cnnDecrypt = Server.CreateObject("ADODB.Connection")
cnnDecrypt.open CONNSTRING
Dim cmd1
Set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = cnnDecrypt
cmd1.CommandText = strSQL
cmd1.CommandType = adCmdText
cmd1.Parameters.Append cmd1.CreateParameter("", adVarBinary, adParamInput, LenB(plainString)+1, plainString)
Set rsDecrypt = cmd1.Execute()
If not rsDecrypt.EOF Then
Decrypt = rsDecrypt.Fields("keycode").Value
Else
Decrypt = "blank"
End If
' Clean Up
rsDecrypt.Close
Set rsDecrypt = Nothing
cnnDecrypt.Close
Set cnnDecrypt = Nothing
End Function
First off, you don't need delimiters around the parameter placeholder. SQL Server will handle it appropriately.
strSQL = "SET NOCOUNT ON;SELECT dbo.Encrypt('xx', ?) as keycode"
Secondly, the Parameters collection is initially empty and must be populated before you try to access it (i.e., the line cmd1.Parameters(0) = plainString). There are several ways of doing this, but I prefer creating the parameters manually using the CreateParameter method:
cmd1.Parameters.Append cmd1.CreateParameter("", adVarChar, adParamInput, Len(plainString), plainString)
Also, it's not apparent from your code, but make sure you've got the ADO constants defined, either by referencing the type library, or by including adovbs.inc.
Related
I am trying to execute a stored procedure using Classic ASP, with two parameters and return the results into a record set that I can loop through and display into a table via a DO WHILE loop.
The problem is, however, I do not get any results when I try and execute the below code. When I use the "RecordCount" property it returns -1 records.
Normally if it were a standard SQL query I would use Response.Write to get the query text and diagnose in SSMS, but i'm not sure how I can troubleshoot when using ADODB.Command. Is there a way to write out exactly what it is doing?
Here is what I have:
Set cmd = Server.CreateObject("ADODB.Command")
Set objRS = Server.CreateObject("ADODB.RecordSet")
With cmd
.ActiveConnection = objConn
.CommandType = 4
.CommandText = "dbo.testCount"
Call .Parameters.Append(.CreateParameter("#Location", adVarChar, adParamInput, 50))
Call .Parameters.Append(.CreateParameter("#Year", adInteger, adParamInput))
.Parameters("#Location").Value = "TestLocation"
.Parameters("#Year").Value = 2014
Set objRS = cmd.Execute()
End With
Set cmd = Nothing
TotalRecords = objRS.RecordCount
Response.Write TotalRecords
^^^^ TotalRecords = "-1" .. ?
I've been searching the depths of the internet and all the solutions I found did not solve this problem.
I am using Visual Web Developer 2010 Express with SQL Server 2008, using VB.
I am trying to execute a stored procedure to insert some data coming from a textbox control to a database, if the id doesn't exist it inserts both the id given in the textbox and the current date (time_scanned_in), if the id exists already, it will insert the current datetime in the [time_scanned_out] column, if all 3 fields in the db are full, it will return #message = 1.
Here is the sql stored procedure:
ALTER PROCEDURE dbo.InsertDateTime
#barcode_id nchar(20),
#message char(1) = 0 Output
AS
BEGIN
if not exists(select * from tblWork where barcode_id = #barcode_id)
begin
INSERT INTO [tblWork] ([barcode_id], [time_scanned]) VALUES (#barcode_id, GetDate())
end
else if exists(select * from tblWork where barcode_id = #barcode_id AND time_scanned_out IS NOT NULL )
begin
SET #message=1
end
else if exists(select * from tblWork where barcode_id = #barcode_id AND time_scanned_out IS NULL)
begin
UPDATE [tblWork] SET [time_scanned_out] = GetDate() WHERE [barcode_id] = #barcode_id
end
RETURN #message
end
If I execute this (by right clicking on the SP), it works flawlessly and returns the values when all fields have been filled.
But when executed through the vb code, no such procedure can be found, giving the error in the title.
Here is the vb code:
Dim opconn As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"
Dim sqlConnection1 As New SqlConnection(opconn)
Dim cmd As New SqlCommand
Dim returnValue As Object
cmd.CommandText = "InsertDateTime"
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = sqlConnection1
sqlConnection1.Open()
With cmd.Parameters.Add(New SqlParameter("#barcode_id", TextBox.Text))
End With
With cmd.Parameters.Add(New SqlParameter("#message", SqlDbType.Char, 1, Label3.Text))
End With
returnValue = cmd.ExecuteScalar()
sqlConnection1.Close()
Note, I haven't done the code for the return part yet, will do that once I get it to locate the SP.
Tried listing all objects with the sys.objects.name for each of the databases in a gridview, it listed everything but the stored procedure I want.
Why is this, any ideas? Would be much appreciated, spent hours trying to find a solution.
If anyone needs any more code or information feel free to ask.
try cmd.parameters.clear() first and then start adding parameters in cmd object. also instead of cmd.executescaler(), try cmd.executenonquery or cmd.executeReader()
Try this
cmd.Parameters.AddWithValue("#barcode_id", TextBox.Text)
SqlParameter prmOut = cmd.Parameters.Add("#message",SqlDbType.Char, 1)
prmOut.Value = Label3.Text
prmOut.Direction = ParameterDirection.InputOutput
cmd.ExecuteNonQuery()
returnValue = prmOut.Value.ToString()
Recreated the whole project with a whole new database, copied all the same code, and now it all works flawlessly! Still have no idea what was wrong, but thank you all, you were all prompt and knowledgable.
Here was the final VB code for anyone who's interested:
Dim myConnection As New SqlConnection(opconn)
Dim cmd As New SqlCommand()
Dim myReader As SqlDataReader
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = myConnection
cmd.CommandText = "InsertTimes"
cmd.Parameters.AddWithValue("#message", OleDbType.Integer)
cmd.Parameters.AddWithValue("#barcode_id", TextBox.Text)
cmd.Parameters("#message").Direction = ParameterDirection.Output
Try
myConnection.Open()
myReader = cmd.ExecuteReader()
Dim returnMessage As String = cmd.Parameters("#message").Value
If returnMessage = 1 Then
label_confirmation.Text = "Record successfully submitted!"
TextBox.Text = ""
ElseIf returnMessage = 2 Then
label_confirmation.Text = "A finish time already exists for the record '" & TextBox.Text & "', would you like to override the finish time anyway?"
button_yes.Visible = True
button_no.Visible = True
ElseIf returnMessage = 3 Then
label_confirmation.Text = "Record submitted, work operation status complete!"
TextBox.Text = ""
End If
Catch ex As Exception
label_confirmation.Text = ex.ToString()
Finally
myConnection.Close()
End Try
I wasn't able to find a question/answer that covers this fully hence why I am asking. What I need to do is run a stored procedure that takes 1 parameter. It will return a set of results which I need to store in a record set. I plan to loop through this recordset later. I'm pretty inexperienced when it comes to older asp, but here is what I have to far:
dim myConn
Set myConn = Server.CreateObject("ADODB.Connection")
myConn.Open = ("DSN=example-dsn;SERVER=example-server;DATABASE=example-db;UID=user;PWD=pass;")
dim oStoredProc : Set oStoredProc = Server.CreateObject("ADODB.Command")
With oStoredProc
.ActiveConnection = myConn
.CommandType = adCmdStoredProc
.CommandText = "myStoredProcedure"
.Parameters.Append(.CreateParameter("#PARAM1", ADODB.adInteger, ADODB.adParamInput, 10, 2012))
Dim rs : Set rs = .Execute()
End With
// Will loop through it here.
My guess is that I'm not setting up the recordset right, but like I said, I'm not really sure. If anyone can point me in the right direction I'd appreciate it!
You will want to make sure your result set is the correct object
set rs = Server.CreateObject("ADODB.Recordset")
Then you will use the open method I think it works something like this:
rs.Open oStoredProc
Then use the other members of the Record Set object to loop through the results.
Alright there were a few things I was doing wrong but here is what ended up working for me. First off it turns out I didn't need a parameter passed in, but that was not the problem anyway. One of the main issues what that 'adCmdStoredProc' wasn't recognized, which is odd because I've seen it used everywhere else, but replacing it with it's corresponding value, 4, did work.
dim myConn, cmd
Set myConn = Server.CreateObject("ADODB.Connection")
myConn.Open = ("DSN=[BLAH];SERVER=[SERVER];DATABASE=[BLAH];UID=[User];PWD=[Pass];")
dim oStoredProc : Set oStoredProc = Server.CreateObject("ADODB.Command")
oStoredProc.CommandType = 4
oStoredProc.CommandText = "StoredProcedureName"
oStoredProc.ActiveConnection = myConn
// Add parameters here if needed.
Dim rs
Set rs = oStoredProc.Execute()
// I Loop through here
rs.Close
myConn.Close
Set rs = Nothing
Set oStoredProc = Nothing
Set myConn = Nothing
I hope this helps if anyone else needs it.
Dim rsStk As New ADODB.Recordset
Set rsStk = cnnPck.Execute("SP_JOB_ALL '" & Trim(te_Item) & "'")
Set Recordset= CONNECTION .Execute()
This one is simple way to do this thing
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
A few years ago we (as a company) faced the scenario of getting our developers to stop writing classic asp pages and switch to .net (and in turn system.data for data access).
As a supposedly ‘short term’ measure I wrote the following class to make the switchover easier for those not used to system.data & all its new objects:
http://www.heavencore.co.uk/forum/viewthread.php?thread_id=185
The main purpose of this class was to keep usage as similar to classic asp as possible & keep the usage VERY simple (plus to add email alerts for error catching yada yada yada):
Public db As New SimpleDataAccess
Public RS As New DataTable
ConnectDatabase()
db.Execute_Query(RS, "SELECT * FROM whatever WHERE IntColumn = " & tools.parseint(EmployeeID, 0) & " or TextColumn = '" & db,Escape("bla'blabla") & "' ORDER BY IntColumn")
For Each DB_Row As DataRow In RS.Rows
response.Write(DB_Row("IntColumn"))
Next
CloseDatabase()
Now, the two main reasons why this class sucks:
Sql Injection stuff (parseint & quote escaping) has to be done outside the class - prone to forgetfulness - Parameterised queries definitely need to be introduced here!
CloseDatabase() has to be called manually at the end of the page - this is often forgot and a connection is left open to the server - even after the page has finished rendering etc
Reasons why this class was good:
Usage of the class was very simple and allowed old classic asp code to be VERY easily converted to .net
Email alerts for query & connection errors was handled invisibly in the class itself
It has worked perfectly for 2+ years now, no problems
My Question:
Are there any other classes / suggestions out there that will allow me to either replace this class but retain the VERY simple usage OR what would be the best way to modify the Execute_Query() and Execute_NonQuery() methods to handle parameterised queries?
Simplicity is key!
PS: Where is a good place to post large chunks of code for use in SO questions? Pastebin etc only keep stuff for a month...
I think this might help you. A large chunk of code. This handles almost every thing you need. You can pass parameters in an array. Also can use with stored procedures as well. Nothing to worry about connection closing.
Hope this helps.
I've always used the functions that came from http://www.fmstocks.com/ (A sample Asp Classic MS application). It's very simple and works with parameters
Example usage:
set rs = RunSQLReturnRs("Select * from Usuario where UsuarioID = ?", _
array(mp("#UsuarioID", adInteger, 0, UsuarioID)))
If not rs.eof then
UsuarioName = rs("FullName")
end if
DbHelper.ASP full code (slightly modified over the years)
<!--#include file="../bus/adovbs.inc"-->
<%
Function GetConnectionString()
GetConnectionString = "file name=c:\udl\miconnstring.udl"
End Function
Function mp(PName , PType , PSize, PValue)
mp = Array(PName, PType, PSize, PValue)
End Function
Function RunSPReturnRS(strSP, 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 = strSP
cmd.CommandType = adCmdStoredProc
cmd.CommandTimeout = 900 ' 15 minutos
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 RunSPReturnRS = rs
End Function
Function RunSP(strSP , params())
On Error resume next
' Create the ADO objects
Dim cmd
Set cmd = server.createobject("ADODB.Command")
' Init the ADO objects & the stored proc parameters
cmd.ActiveConnection = GetConnectionString()
cmd.CommandText = strSP
cmd.CommandType = adCmdStoredProc
cmd.CommandTimeout = 900 ' 15 minutos
collectParams cmd, params
' Execute the query without returning a recordset
cmd.Execute , , adExecuteNoRecords
If err.number > 0 then
BuildErrorMessage()
exit function
end if
' Disconnect the recordset and clean up
Set cmd.ActiveConnection = Nothing
Set cmd = Nothing
Exit Function
End Function
Function RunSQL(strSP , params())
On Error resume next
' Create the ADO objects
Dim cmd
Set cmd = server.createobject("ADODB.Command")
' Init the ADO objects & the stored proc parameters
cmd.ActiveConnection = GetConnectionString()
cmd.CommandText = strSP
cmd.CommandType = adCmdText
cmd.CommandTimeout = 900 ' 15 minutos
collectParams cmd, params
' Execute the query without returning a recordset
cmd.Execute , , adExecuteNoRecords
If err.number > 0 then
BuildErrorMessage()
exit function
end if
' Cleanup
Set cmd.ActiveConnection = Nothing
Set cmd = Nothing
Exit Function
End Function
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
cmd.CommandTimeout = 900 ' 15 minutos
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
Function RunSPReturnInteger(strSP , params())
On Error resume next
' Create the ADO objects
Dim cmd
Set cmd = server.createobject("ADODB.Command")
' Init the ADO objects & the stored proc parameters
cmd.ActiveConnection = GetConnectionString()
cmd.CommandText = strSP
cmd.CommandType = adCmdStoredProc
cmd.CommandTimeout = 900 ' 15 minutos
collectParams cmd, params
' Assume the last parameter is outgoing
cmd.Parameters.Append cmd.CreateParameter("#retval", adInteger, adParamOutput, 4)
' Execute without a resulting recordset and pull out the "return value" parameter
cmd.Execute , , adExecuteNoRecords
If err.number > 0 then
BuildErrorMessage()
exit function
end if
RunSPReturnInteger = cmd.Parameters("#retval").Value
' Disconnect the recordset, and clean up
Set cmd.ActiveConnection = Nothing
Set cmd = Nothing
Exit Function
End Function
Private Sub collectParams(cmd , argparams())
Dim params , v
Dim i , l , u
params = argparams
For i = LBound(params) To UBound(params)
l = LBound(params(i))
u = UBound(params(i))
' Check for nulls.
If u - l = 3 Then
If VarType(params(i)(3)) = vbString Then
If params(i)(3) = "" then
v = null
else
v = params(i)(3)
end if
Else
v = params(i)(3)
End If
If params(i)(1) = adLongVarChar Then
Dim p 'As New Parameter
Set p = cmd.CreateParameter(params(i)(0), params(i)(1), adParamInput)
p.Attributes = adParamLong + adParamSigned
If Not IsNull(v) Then
'Seteo para text columns is not null
p.AppendChunk v
p.Size = Len(v)
Else
'Seteo para text columns is null
p.Value = v
p.Size = 10000
End If
cmd.Parameters.Append p
Else
cmd.Parameters.Append cmd.CreateParameter(params(i)(0), params(i)(1), adParamInput, params(i)(2), v)
End If
Else
RaiseError m_modName, "collectParams(...): incorrect # of parameters"
End If
Next
End Sub
%>
I know it is a common error, but I still can't solve it myself.
What I am trying to do is I have a SELECT item called status that allow the user to choose their employment status, I want to simply get the result and update the user_table(access file) status cell.
Any reply will be greatly appreciated!
The Code is below:
<!--#include file="../conn/conn.asp"-->
<%
id=request.QueryString("id")
status=request.Form("status")
sql="select * from user_table where id="&id
set rs=conn.execute(sql)
sql="update user_table set Status='"+status+"' where id="&id
'response.Write sql
conn.execute(sql)
conn.close
response.Write "<script>alert('Change Sucessful!');</script>"
set conn=nothing
response.end()
%>
I think you may be having a problem with conn.execute(sql) as well as response.end()
To fix it, you need to do either:
conn.execute sql
or
Call conn.execute(sql)
But, yeah, you should follow other comments posted as your technique has security issues. You should consider changing it to use parameters:
<!--#include file="../conn/conn.asp"-->
<%
id = request.QueryString("id")
status = request.Form("status")
sql = "select * from user_table where id = #id"
Set cmd = CreateObject("ADODB.Command")
cmd.CommandText = sql
Set cmd.ActiveConnection = conn
cmd.Prepared = True
cmd.Parameters.Refresh
cmd.Parameters("#id") = id
Set rs = cmd.Execute
Set rs = nothing
Set cmd = nothing
sql = "update user_table set status = #status where id = #id"
Set cmd = CreateObject("ADODB.Command")
cmd.CommandText = sql
Set cmd.ActiveConnection = conn
cmd.Prepared = True
cmd.Parameters.Refresh
cmd.Parameters("#status") = status
cmd.Parameters("#id") = id
Set rs = cmd.Execute
Set rs = nothing
Set cmd = nothing
response.Write "<script>alert('Change Sucessful!');</script>"
Set conn = nothing
response.end
%>
I'm guessing conn.asp leaves conn open? otherwise you need to open it. Also, what shows when you uncomment the response.write sql line?
And, you are definitely opening yourself to hackers. You need to 'clean' anything that comes from a request.form or request.querystring (with at the very least, a replace(..., "'", "''"), or much better, use stored procedures instead of straight sql