how to count records in ASP classic? - asp-classic

I'm not quite familiar with programming ASP classic. I just need a small code to run on my webpage. How do i count the record of the returned query?
<%
Set rsscroll = Server.CreateObject("ADODB.Recordset")
Dim strSQLscroll, rsscroll
strSQLscroll = "SELECT * FROM tblItems where expiration_date > getdate() order by expiration_date desc;"
rsscroll.open strSQLscroll,oConn
%>
thanks,

It is possible (but not recommended) to use the RecordCount property on the Recordset object as follows:
iTotalRecords = rsscroll.RecordCount
If your table is really large, this can take a long time to run. I would instead run a separate SQL query to get the total records
SQL = "SELECT COUNT(*) AS TotalRecords FROM tblItems WHERE expiration_date > getdate() "
set rsRecordCount = conn.Execute(SQL)
if not rsRecordCount.Eof then
iTotalRecords = rsRecordCount.Fields("TotalRecords")
else
iTotalRecords = 0
end if
rsRecordCount.Close
set rsRecordCount = nothing

rsscroll.RecordCount

One simple solution's to use the SQL COUNT method. This assumes you want the number of rows and not the data itself.
<%
Set rsscroll = Server.CreateObject("ADODB.Recordset")
Dim strSQLscroll, rsscroll, intRow
strSQLscroll = "SELECT COUNT(*) AS Total FROM tblItems WHERE expiration_date > getdate();"
rsscroll.open strSQLscroll, oConn
response.write rsscroll("Total")
rsscroll.close: set rsscroll = nothing
oConn.close: set oConn = nothing
%>
This returns one row with a single value called "Total." (Read on if you need both the row count and data.)
Your query code uses a default RecordSet, which returns data in "forward-only" mode for efficiency. It'll step through row-by-row, but doesn't know the actual count. (This mode also sets the RecordSet.RecordCount to -1, so the field isn't useful for you.)
RecordSet.Open's "Cursor Type" parameter lets you change to "Keyset" mode (parameter value 1), which does set the RecordCount field to the number of data rows. ("Lock Type" and "Command Type" parameters included for completeness, but they don't figure into this answer.)
RecordsetObject.Open "TableName|SQLStatement", ConnectionObject [,Cursor Type] [,Lock Type] [,Command Type]
Add this parameter to your code's RecordSet.Open call and then check RecordCount.
<%
Set rsscroll = Server.CreateObject("ADODB.Recordset")
Dim strSQLscroll, rsscroll, intRow
strSQLscroll = "SELECT * FROM tblItems where expiration_date > getdate() order by expiration_date desc;"
rsscroll.open strSQLscroll, oConn, 1
intRow = rsscroll.RecordCount
' ... do something with intRow
rsscroll.close: set rsscroll = nothing
oConn.close: set oConn = nothing
%>
If database performance means anything to your situation, the RecordSet.GetRows() method's much more efficient.
<%
Dim rsscroll, intRow, rsArray
Set oConn = CreateObject("ADODB.Connection")
oConn.open "<connection string>"
strSQLscroll = "SELECT * FROM tblItems where expiration_date > getdate() order by expiration_date desc"
Set rsscroll = conn.execute(strSQLscroll)
if not rsscroll.eof then
rsArray = rsscroll.GetRows()
intRow = UBound(rsArray, 2) + 1
response.write "rows returned: " & intRow
' ... do any other operations here ...
end if
rsscroll.close: set rsscroll = nothing
oConn.close: set oConn = nothing
%>

I usually use a separate query like "select count(*) from table " to get counts because I usually need not only the count but a summation of the number of units or the average price or whatever and it's easier to write a separate query than to make more variables and say "TotalUnits = TotalUnits + rs("Units").value" inside the loop to display the results. It also comes in handy for the times you need to show the totals above the results and you don't want to loop though the recordset twice.

Get in the habbit of storing returned data in arrays. This is amazingly faster to iterate than using an open record set. Also, specify the fields to select when doing this as you have to explicitly reference the array index.
<%
Set rsscroll = Server.CreateObject("ADODB.Recordset")
Dim strSQLscroll, rsscroll
Dim arrCommon
'Open recordset, copy data to array
strSQLscroll = "SELECT field1, field2, field3 FROM tblItems where expiration_date > getdate() order by expiration_date desc;"
rsscroll.open strSQLscroll,oConn
arrCommon = rsscroll.getRows()
rsscroll.close
'Get the total records in this array
response.write ubound(arrCommon, 2);
'Loop...
for i = 0 to ubound(arrCommon, 2)
' This prints field 3
response.write arrCommon(2, i)
next
%>

You could just change your SQL to count the records:
strSQLscroll = "SELECT count(*) as Total FROM tblItems where expiration_date > getdate();"
Then you just need to response.write rsscroll("Total")

<%
' TableID = your tables ID...
Set rsscroll = Server.CreateObject("ADODB.Recordset") Dim strSQLscroll, rsscroll strSQLscroll = "SELECT *,(SELECT TableID FROM tblItems where expiration_date > getdate()) As Count FROM tblItems where expiration_date > getdate() order by expiration_date desc;"
rsscroll.open strSQLscroll,oConn
Count = rsscroll("Count")
%>

You can try this
Dim count
count = 0
if strSQLscroll.eof <> true or strSQLscroll.bof <> true then
while not strSQLscroll.eof
count = count+1
strSQLscroll.movenext
wend
end if
response.write(count)

If you are using MySQL try this:
Dim strSQLscroll, rsscroll, countrs
Set rsscroll = Server.CreateObject("ADODB.Recordset")
rsscroll.CursorLocation = 3
rsscroll.open "SELECT * FROM tblItems where expiration_date > getdate()
order by expiration_date desc;",oConn
countrs = rsscroll.recordcount

Related

Stop While Not when the correct answer is found

I've got a table with six records, so far. Everyone has 2 fields: Min_lenght, Max_lenght.
Those field define a range, so the first item has Min_lenght = 160, Max_lenght = 179 and so on.
When defining 1 value (custom_lenght) I need to stop the SQL when this values is in range.
So (custom_lenght > Min_lenght) AND (custom_lenght < Max_lenght)
custom_lenght = cint(request("custom_lenght"))
Set objRS2 = Server.CreateObject("ADODB.Recordset")
sql2 = "SELECT * FROM tbl_model where Order by ID_model ASC"
objRS2.Open sql2, ConString
If Not objRS2.EOF Then
While Not objRS2.EOF
Min_lenght = cint(objRS2("Min_lenght"))
Max_lenght = cint(objRS2("Max_lenght"))
order = objRS2("order")
Price = objRS2("price")
if (custom_lenght > Min_lenght ) AND (custom_lenght < Max_lenght) then
Outofrange="True"
else
Outofrange = "False"
End If
objRS2.MoveNext
Wend
End If
PuliziaRS(objRS2)
The problem is, the SQL browse all the records. I need to obtain the data (price and order) of the item that falls between the range
Change your SQL statement to "SELECT order, price FROM tbl_model WHERE (Min_length < " & custom_length & " AND Max_length > " & custom_length & ") ORDER BY ID_Model"
This will limit the recordset to records that match your custom_length.
As a alternative;
custom_lenght = cint(request("custom_lenght"))
Set objRS2 = Server.CreateObject("ADODB.Recordset")
sql2 = "SELECT order, price FROM tbl_model WHERE " & custom_lenght & " BETWEEN Min_lenght AND Max_lenght Order by ID_model ASC"
objRS2.Open sql2, ConString
If Not objRS2.EOF Then
order = objRS2("order")
Price = objRS2("price")
Outofrange = "True"
Else
Outofrange = "False"
End If
objRS2.Close

Stored Procedure Variable (Code error I believe is there)

I am trying to create a script to tidy all the columns and rows in SQL Server (I will be doing more than trimming but once it works I can plug into app-code I have already)
I think I am there but it does not seem to update - maybe the stored procedure is wrong? I believe the error is here.. -- I have looked around about variables in stored procedures and think it looks correct to me.
Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
Full script...
Protected Sub btnTest_Click(sender As Object, e As System.EventArgs) Handles btnTest.Click
'Select the column names
Dim cn As SqlConnection = New SqlConnection()
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim i As Integer = 0
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
' this gets the colum name
cmd.CommandText = "select COLUMN_NAME FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'systemUsers'"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the command (in this case only one row).
CheckBoxList1.Items.Clear() 'remove all items for the new list
Do While dr.Read()
i = i + 1
Session.Item("ColumnName" & i) = dr.Item("COLUMN_NAME").ToString()
Loop
' Close your connection to the DB.
dr.Close()
cn.Close()
Dim j As Integer = 1
For j = 1 to i
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
cmd.CommandText = "Select * From [systemUsers]"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the cmd (in this case only one row).
Dim vName As String = ""
If vName = "ID" Then
'skip as ID should never be edited!!
Else
Do While dr.Read()
vName = Session.Item("ColumnName" & j).ToString ' put into vName for Stored Procedure
Dim sConnString As String = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
Dim dsNames As SqlDataSource
dsNames = New SqlDataSource
dsNames.ConnectionString = sConnString
Dim sSQL As String
sSQL = "SPTidy"
dsNames.UpdateCommand = sSQL
dsNames.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure
dsNames.UpdateParameters.Clear()
dsNames.UpdateParameters.Add("ID", dr.Item("ID").ToString())
dsNames.UpdateParameters.Add("Update", Trim(dr.Item(vName).ToString()))
dsNames.UpdateParameters.Add("ColumnName", vName)
dsNames.Update()
dsNames = Nothing
Loop
End If
j = j + 1
' Close your connection to the DB.
dr.Close()
cn.Close()
Next
End Sub
Stored procedure:
create PROCEDURE [dbo].[SPTidy]
#ID bigint,
#Update nvarchar(max),
#ColumnName nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
END
That code won't throw an error message because it's simply updating the variable. To have a dynamic column name you need to use dynamic SQL (or complicated case statements) but dynamic SQL is better in this instance.
DECLARE #sql nvarchar(max) = '';
SET #sql = N'UPDATE systemUsers SET ' + #ColumnName + N' = ' + #Update + N' WHERE ID=' + #ID
EXEC sp_executesql #sql
Hope this helps :)

Output parameter used to insert a row in same table

Thanks for your help Guys
I am working on a Asp.net based project and my requiremnent is to generate a PARTNO with the combination of MaterialType+ProductID and - 4digit random number
NOTE: ProductID is Primary key and also set it to output parameter
for example If material type is 500 and product ID generated 55 and random no generated 5434, then part no become 555-5434
Now my question is how could I store partno in same table, I am somewhat trying like that
Connection.Open()
Dim trn As SqlClient.SqlTransaction
trn = Connection.BeginTransaction
Using trn
Dim sqlcode As New SqlParameter("#ProductID", Products.ProductID)
sqlcode.Direction = ParameterDirection.InputOutput
Using Command As New SqlCommand("Product_Write", Connection, trn)
Command.CommandType = CommandType.StoredProcedure
Command.Parameters.Add(sqlcode) Command.Parameters.AddWithValue("#MaterialType", Materialtype.MaterialTypeCode)
Command.Parameters.AddWithValue("#CategoryID", category.CategoryId)
Command.Parameters.AddWithValue("#ProductName", Products.ProductName)
Command.Parameters.AddWithValue("#ProductDescription", Products.ProductDescription)
Command.Parameters.AddWithValue("#ProductActive", Products.ProductActive)
Command.Parameters.AddWithValue("#ProductImage", Products.ProductImage)
Command.Parameters.AddWithValue("#PartNo", 0)
Command.ExecuteNonQuery()
Products.ProductID = CInt(sqlcode.Value)
'Insert the part no
Dim random As New Random()
Dim value As Integer = random.Next(9999)
Dim PartNo As String = CType((Materialtype.MaterialTypeCode + Products.ProductID).ToString + "-" + value.ToString, String)
'Dont know what to do
trn.Commit()
Connection.Close()
End Using
End Using
End Using
Return Products
End Function
ALTER PROCEDURE [dbo].[Product_Write]
#ProductID bigint OUTPUT,
#MaterialType int,
#CategoryID bigint,
#ProductName VARCHAR(MAX),
#ProductDescription VARCHAR(MAX),
#ProductActive Bit,
#ProductImage VARCHAR(MAX),
#PartNo VARCHAR(30)
AS
IF (#ProductID=0)
BEGIN
INSERT INTO T_Product(
MaterialType,
CategoryID,
ProductName,
ProductDescription,
ProductActive,
ProductImage,
PartNo)
VALUES(
#MaterialType,
#CategoryID,
#ProductName,
#ProductDescription,
#ProductActive,
#ProductImage,
#PartNo)
SET #ProductID=SCOPE_IDENTITY()
END
ELSE
UPDATE T_Product SET
MaterialType=#MaterialType,
CategoryID=#CategoryID,
ProductName=#ProductName,
ProductDescription=#ProductDescription,
ProductActive=#ProductActive,
ProductImage=#ProductImage,
PartNo=#PartNo
WHERE ProductID=#ProductID
Please help me out
Thanks
If you can update the Stored Procedure you would need something along these lines
declare #id int
set #id = SCOPE_IDENTITY()
UPDATE <Table> Set PartNo = MaterialType + convert(varchar(max),#id) + convert(varchar(4),CEILING(9999*RAND())) Where ID = #id

Copy records to another recordset using Active Server Page

I'm programming in Classic ASP. I'm trying to do the paging. My backend is SQL CE 3.5. Unfortunetly, it doesn't support paging in SQL Query (Like row_number() in sql server).
So I go with ASP Paging. But when i ask to the recordset, give me the first 10 records by setting the rs.PageSize and rs.AbsolutePage and all, it gives me all records. So I planned to copy only first 10 rows from the resultant recordset to another new recordset. So I coded like below:
Set rsTemp = CopyRecordsetStructure(objRs)
rsTemp.Open
iRecordsShown = 0
Set objFields = objRs.Fields
intFieldsCount = objFields.Count-1
Do While iRecordsShown < intPageSize And Not objRs.EOF
rsTemp.AddNew
For Idx = 0 To intFieldsCount
rsTemp.Fields(Idx).Value = objRs.Fields(Idx).Value
Next
rsTemp.Update
iRecordsShown = iRecordsShown + 1
objRs.MoveNext
Loop
Public Function CopyRecordsetStructure(ByVal rs)
Dim rsTemp
Set rsTemp = CreateObject("ADODB.Recordset")
Set objFields = rsTemp.Fields
intFieldCount = objFields.Count - 1
For Idx = 0 To intFieldCount
rsTemp.Fields.Append objFields(Idx).Name, _
objFields(Idx).Type, _
objFields(Idx).DefinedSize
Next
Set CopyRecordsetStructure = rsTemp
End Function
The issue is i could not open the" rsTemp". It throws me error
The connection cannot be used to perform this operation. It is either closed or invalid in this context.
If I use some dummy query and connection it doesn't work.
Please help to copy the records from one recordset to another new record set.
Thanks in advance
Ganesh.
Not sure, but this looks wrong
Set objFields = rsTemp.Fields
Shouldn't it be
Set objFields = rs.Fields
With the comments and fixed in the above comments, the function should be updated Set objFields = rs.Fields to:
Usage:
Dim rsTemp
Set rsTemp = CopyRecordset(rsPadicon)
Update Code
Public Function CopyRecordset(rs)
Dim rsTemp, objFields, intFieldsCount, intPageSize
Set rsTemp = CopyRecordsetStructure(rs)
rsTemp.Open
Set objFields = rs.Fields
intFieldsCount = objFields.Count-1
response.write("<li> rs.RecordCount :" & rs.RecordCount & "</li>")
' response.write("<li> intFieldsCount :" & intFieldsCount & "</li>")
rs.MoveFirst
Do While Not rs.EOF
rsTemp.AddNew
Dim i
For i = 0 to intFieldsCount 'use i as a counter
' response.write("<li> Name :" & rs.Fields(i).Name & "</li>")
' response.write("<li> Value :" & rs.Fields(i).Value & "</li>")
if Not IsNull(rs.Fields(i).Value) then
rsTemp.Fields(i).Value = rs.Fields(i).Value
End if
Next
rsTemp.Update
rs.MoveNext
Loop
Set CopyRecordset = rsTemp
End Function
Public Function CopyRecordsetStructure(ByVal rs)
Dim rsTemp, objFields, intFieldCount, Idx
Set rsTemp = CreateObject("ADODB.Recordset")
Set objFields = rs.Fields
intFieldCount = objFields.Count - 1
For Idx = 0 To intFieldCount
rsTemp.Fields.Append objFields(Idx).Name, _
objFields(Idx).Type, _
objFields(Idx).DefinedSize
Next
Set CopyRecordsetStructure = rsTemp
End Function

Updateing NText causing long delay/timeouts

I'm trying to update an NText field in SQL 2000 using Classic ASP. Here is the code I'm using to do it. Any one have any pointers on how to maybe speed it up? Or am I stuck with it.
set Cnn = server.CreateObject("ADODB.connection")
Cnn.ConnectionString = Application("Cnn_ConnectionString")
Cnn.open
set rs = server.CreateObject("ADODB.Recordset")
rs.CursorType = adoOpenDynamic
rs.LockType = adLockOptimistic
conChunkSize = 100
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
lngOffset = 0
lngLogoSize = len(request("txtMyEntry"))*2
Do while lngOffset < lngLogoSize
varChunk = LeftB(RightB(request("txtMyEntry"), lngLogoSize - _
lngOffset), conChunkSize)
rs("MyDataField").AppendChunk varChunk
lngOffset = lngOffset + conChunkSize
Loop
rs.Update
rs.Close
Oh and this code is almost verbatim from the MSDN site.
First I would eliminate the chunking which is so 90's.
Then there is:-
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
Yikes! You'd like to think that ADO intelligently asked SQL server to find that record based on the indexed MyDataId field but bet it doesn't. Its most likely pulling the entire contents of the table across until the record is arrived at.
This really should be done with an UPDATE T-SQL statement and an ADODB.Command object.
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = cnn
cmd.CommandType = 1 '' // adCmdText
cmd.CommandText = "UPDATE MyTable SET MyDataField = ? WHERE MyDataId = ?"
cmd.Parameters.Append cmd.CreateParameter("dataField", 203, 1, Len(txtMyEntry), txtMyEntry) '' // 203 = asLongVarWChar, 1 = adParamInput
cmd.Parameters.Append cmd.CreateParameter("id", 3, 1, , CInt(DataID)) '' // 3 = adInteger
cmd.Execute

Resources