asp classic retrieve and display single recordset - asp-classic

i hv a code that need me to find only a single line of recordset from the database into the variable.
dim Connect,conn_,data,sql
Set Connect = Server.CreateObject("ADODB.Connection")
Connect.Open "toServer"
sql = "SELECT * from sppro where proj_name='pname'"
set Data = Connect.Execute(sql)
response.write data("proj_id")
i just cant find to correct way to retrieve and view single record set... i found something about cursor, but i dont understand it at all...
can anyone pls explain to me?
edit:
error tht i got with this code is as below.
ADODB.Field error '80020009'
Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.
/bkpi-msn/Include/ServerSideAjax.asp, line 0

If I understand correctly you already know how to display one record from a database, but now you want to display more than one record. Is that right?
With some changes to your code, you can loop though all records:
dim Connect,conn_,data,sql
Set Connect = Server.CreateObject("ADODB.Connection")
Connect.Open "toServer"
sql = "SELECT * from sppro where proj_name='pname'"
set Data = Connect.Execute(sql)
Do Until Data.Eof
response.write data("proj_id")
Data.MoveNext
Loop
Edit: to retrieve just one row, you can use the following. It's basically the same, except there is a check to ensure there is at least one record, and no need to loop through the recordset.
dim Connect,conn_,data,sql
Set Connect = Server.CreateObject("ADODB.Connection")
Connect.Open "toServer"
sql = "SELECT * from sppro where proj_name='pname'"
set Data = Connect.Execute(sql)
If Not Data.Eof Then
response.write data("proj_id")
End If

Related

Stored Procedure Not Working From ASP Page

we are having issues with a stored procedure. When calling it from our website via asp/vb.net it seems to not be executing properly. If I run it from SSMS it works.
I have run the debugger when the call is being placed, the parameters being passed in are correct at the time of the ExecuteNonQuery() call but it is not generating any records in the related tables like it should. If I use the same values seen while debugging our website directly in SSMS, the stored procedure creates the expected records.
Here is our stored procedure:
ALTER PROCEDURE [dbo].[CopyGoals](
#OldVisitID int,
#NewVisitID int,
#CreatedBy NVarChar(30)
) AS BEGIN
declare #GoalMapping As Table(OldGoalID int,NewGoalID int);
Merge Into VisitGoals
Using(
select GoalsID,Goal,ProgressNote,Progress,Completed,CreatedOn,CreatedBy,VisitID
From VisitGoals
Where VisitID = #OldVisitID
) As Src
On 1 = 0
When Not Matched By Target Then
Insert (Goal,ProgressNote,Completed,VisitID,Progress, CreatedOn, CreatedBy)
Values (Src.Goal, Src.ProgressNote, Src.Completed, #NewVisitID, Src.Progress, GetDate(), #CreatedBy)
Output Src.GoalsID As OldGoalID, inserted.GoalsID as NewGoalID
Into #GoalMapping;
Insert Into SubGoals(GoalID,VisitID,GoalText,HasCompleted,WillComplete,GoalStatus)
(
Select GM.NewGoalID, #NewVisitID, SG.GoalText, SG.HasCompleted, SG.WillComplete, SG.GoalStatus
From SubGoals As SG inner join #GoalMapping As GM on SG.GoalID = GM.OldGoalID
Where SG.VisitID = #OldVisitID
)
END
Here is the procedure call from our website page:
Dim conStr As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
Dim curUsr As New Supervisor(Context.User.Identity.Name, True)
Using con As New SqlConnection(conStr)
Using cmd As New SqlCommand("CopyGoals", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#OldVisitID", SqlDbType.Int).Value = oldVID
cmd.Parameters.Add("#NewVisitID", SqlDbType.Int).Value = newVID
cmd.Parameters.Add("#CreatedBy", SqlDbType.NVarChar, 30).Value = curUsr.Name
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Using
End Using
What this procedure should do, and does if run from SSMS, is look at our Goals table with the existing IDs matching a foreign key corresponding to the VisitID in a different table to find all goals associated with that old visit.
It them copies the goal information and inserts it into the Goals table, outputting the old goal IDs and the newly inserted goal IDs into the #GoalMapping table.
It then looks into our SubGoals table and does a similar thing by copying each subgoal related to the goals we just copied. For whatever reason, this procedure does not execute properly when called from our page even when it runs in SSMS when we feed it the same input values as seen during debugging of the page. There are no errors reported in chrome's debugger, we tried wrapping execute in a try with an SQL and normal exception but neither of them tripped. We are pretty stumped. Maybe someone will spot something we haven't over the last few days.
Here is the output from Sql Profiler:
Okay, I finally figured it out. There was a permission issue as Mohsin suggested. I logged in as the user that we use for our ASP.net connection strings and attempted to run the query in question and it failed to generate the records from SSMS. So after some digging I found this question:
Stored Procedure and Permissions - Is EXECUTE enough?
Which lead to this question when I got the same error:
SQL Server principal "dbo" does not exist,
Combined together, the answers to these questions helped me fix the issue.

Microsoft Cursor Engine error '80040e21' Multiple-step operation generated errors. Check each status value

I am having a look on an old web application written in the 90s in VB6 and Active Server Pages (JScript). The application retrieves some data from the database and stores it in a recordset which it is using to update. When it attempts to update a field (see below) it gives an '80040e21' error.
rsSave.Fields('text') = Request.Form('strText').Item(i); // this line fails
I have checked the type of the field and it is adVarWChar (202). I have checked the size of the 'text' field which is 2000, way bigger than what is comming from the form. I checked the status of all fields and they are all adFieldOK (0). In other words any of the usual suspects giving normally this error are ok.
The COM+ object that is creating, filling and then returning the recordset is doing the following:
'Initialize command object
Set oCmd = CreateObject("ADODB.Command")
With oCmd
.CommandType = adCmdText
.CommandText = strsql
End With
Set cn = CreateObject("ADODB.Connection")
'Open connection to database
cn.Open strConn
oCmd.ActiveConnection = cn
Set rs = CreateObject("ADODB.Recordset")
With rs
Set .Source = oCmd
.LockType = adLockBatchOptimistic
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.Open
Set .ActiveConnection = Nothing
End With
I tried using adLockOptimistic, but no luck.
Last but not least, this application was using initially an old Microsoft OleDb provider for Oracle that was no longer compatible with windows server 2008. We had to use a new provider and since then some things needed to be adjusted in order to work properly.
Any ideas?
I used to get these when I was writing from VB6 to a DB2 database using IBM OLE DB Provider. It was always related to either the data being incompatible with the underlying field type, or the content was too large. Check dates, strings being written into integers, vice versa, etc.
I would try a process of elimination. Write data only one field, defaulting the others to the minimum thy will accept, then keep adding fields with the expected data until it triggers an error. At least it will tell you which field it is.
Sorry I don't have much more to offer.

classic asp query a recordset rather than a table

So, you have a recordset created like this:
Set rs = Server.CreateObject("ADODB.Recordset")
And you fill it like this:
rs.Open queryString, AuthConn, adOpenKeyset, adLockReadOnly
My question is, I want a second recordset that is a subset of the first (rs) recordset, can you do this in classic asp
Set rs2 = Server.CreateObject("ADODB.Recordset")
My immediate guess is that it would be something like this
rs2.Open queryString, rs, adOpenKeyset, adLockReadOnly
Why you ask? Well we have an older site that we are updating and adding new features too and rather than change a LOT of code I was wondering if I could be sneaky and use a setset of an already created (large) recordset, to save on another query to the db etc. Just wondering if it can be done.
Thanks,
You can use the Clone method to create a duplicate recordset, then use Filter to reduce the dataset to what you're interested in. For example:
Dim rs, rs2
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open queryString, AuthConn, adOpenKeyset, adLockReadOnly
Set rs2 = rs.Clone()
rs2.Filter = "Field1 = 'foo'"
The string form of Filter is basic; it's pretty much <Field> <op> <value>. You can combine multiple expressions using AND and OR, but even that has some limitations (see the documentation link for the full details).
For more complex filtering, you can pass the Filter property an array of Bookmark objects. In this case, you loop through the recordset (or a clone of the recordset), testing each record by whatever complex criteria you have. If the record passes the test, you save its Bookmark to an array or other collection. Then, you can set the Filter property to your array of Bookmarks and you have a custom-filtered recordset.
'Note that I haven't tested this code
Dim rs, rs2, bookmarks
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open queryString, AuthConn, adOpenKeyset, adLockReadOnly
Set rs2 = rs.Clone()
bookmarks = Array()
Do Until rs2.EOF
If rs2("Field1") = 2 * rs2("Field2") Then
ReDim Preserve bookmarks(UBound(bookmarks) + 1)
bookmarks(UBound(bookmarks)) = rs2.Bookmark
End If
rs2.MoveNext
Loop
rs2.Filter = bookmarks
' Now rs2 contains only records where Field1 = 2*Field2
You can use this same technique to get unique values (aka DISTINCT) by using a Dictionary object to store the unique key values. Doing a DISTINCT on multiple fields is a bit trickier. What I've done is the past is to combine the multiple fields using a separator that won't be in the data (such as a pipe |). That's not always possible, though.
The recordset object can be opened only by a "connection" object, you cannot replace the connection object with another recordset object as shown above, however if you modify the querystring object and open the desired subset through your own query you can achieve this.
Please post querystring if you have difficulty making the subset.
Obviously you can create a second query and recordset and run it over and over again inside "do while not rs.eof............loop" - I'm guessing that's what you want to avoid.
You might want to take a look at Datashaping. There's an article about it here. It's old, but then this is Classic ASP
https://web.archive.org/web/20210513001641/https://www.4guysfromrolla.com/webtech/092599-1.shtml
There also used to be a page on MSDN called "Using Data Shape to create hierarchical recordsets". You'll find loads of links to it on Google but they all take you to a 404 page on a resource for .net developers now :(

Classic ASP: RecordSet Field giving no value

I'm not really an ASP developer, so a little bit lost.
I have the following data access code:
sSQL = "SELECT answer_id, company_name, old_access_company_name, answer, flag_asker_notified FROM Q01_ask_sheiiba_answer_company2 WHERE question_id="& sQuestion_id &" ORDER BY answer_id"
rs.open sSQL, conn
DO WHILE NOT rs.EOF
Response.Write(rs.Fields("answer"))
rs.MoveNext
LOOP
I have tested that the sql query is built properly by outputting it to the response before it is called. It produces the following query:
SELECT answer_id, company_name, old_access_company_name, answer, flag_asker_notified
FROM Q01_ask_sheiiba_answer_company2
WHERE question_id=988
ORDER BY answer_id
When I copy that exact query to sql management studio and run it I get the expected results of 5 rows and each row containing data in every cell, BUT, when I run it through the above code, I get the same 5 rows with the same cell data, EXCEPT for the answer column, which is empty!
What am I missing?
Thanks in advance
There are two things you might want to try:
Put your text field at the end of the query. For example:
SELECT answer_id, company_name, old_access_company_name, flag_asker_notified, answer
If this doesn't give you the results, you might want to try:
WHILE NOT rs.EOF
theanswer=rs("answer")
Response.Write(theanswer)
rs.movenext
wend
Text and Memo fields can play a little havoc with ASP.
EDIT: Another thing that you can try is:
rs.CursorLocation = adUseClient
or
rs.CursorLocation = 3
The problem is that the ODBC driver can't access large text blobs as strings; you need to access them as chunked BLOB data.
I advise instead to dump the ODBC connection and connect using the OLE-DB driver directly. This will let you access that column as if it was just another varchar column.
I just had a similar problem (I think). I converted a varchar field to text. When I did so, I found that the text field seemed to "disappear" from my selected record set. I my case, I discovered that you can reference the text field ONLY ONCE. After that, it seems to disappear. Accordingly, for the text field, I now simply move it into a string variable and then operate on the string. That solved my problem.
John
Had the same problem and found the solution here https://web.archive.org/web/20170224013842/http://www.4guysfromrolla.com/aspfaqs/ShowFAQ.asp?FAQID=80
Basically when you open the recordset (not connection.execute) use the options adOpenKeyset (val 1) and adUseClient (val 3), and the text filed should be the last in your field list in strSql
example: rs.Open strSql, dbConn, adOpenKeyset, adUseClient

Add record on button click only

I have a form that has the 'data entry' property set to yes. It is bound to a table. When I start filling in the form it automatically saves it. I do not want this to happen. I only want the form to save to the table when I press a button. Any easy way to do this? w/o vba. If i can only do this with vba let me know how to do it that what.
The best way to do this is with an unbound form. When the user clicks save, you can run a query to update your table from the controls.
Using a recordset
Dim rs As Recordset
Set rs=CurrentDB.Openrecordset("MyTable")
rs.AddNew
rs!Field1 = Me.Field1
rs.Update
If you wanted to update a record where you already knew the primary key, you could say:
Dim rs As Recordset
Set rs=CurrentDB.Openrecordset("SELECT * FROM MyTable WHERE ID=" & Me.txtID)
rs.Edit
rs!Field1 = Me.Field1
rs.Update
Using a query that you have created in the query design window
SQL for the query
INSERT INTO MyTable (Field1)
VALUES ( Forms!MyForm!Field1 )
VBA
This will give a warning
DoCmd.OpenQuery "MyQuery"
This will not
CurrentDb.Execute "Query2", dbFailOnError
You could also use dynamic SQL or a query with parameters that you assign in code.

Resources