Asp-Classic ADODB Recordset missing Records - database

one of the simplest Components in my website just stopped working from one day to the other without any changes in Code.
'Connection Declaration as connection
Set rs = Server.CreateObject ("ADODB.Recordset")
rs.Open "SELECT * FROM tablename ORDER BY id DESC", connection, 1, 3
while not rs.EOF
'writing some Table from the records in DB
'Simplified Code %>
<tr><td><%=rs("id")%></td><td><%=rs("description")&></td></tr>
<%
rs.MoveNext
Wend
in my Database i have verified the extraordinary number of 30 records :(
when above code is executed i see 2 of them
This tells me two things,
first: the tablename is Correct and the connection to the Database is established
second: the table-generation in itself is correct
I also have a smaller Testing-System. there the exact same code on a sample Database produces the expected Results.
Unfortunately i have no means of "instant-access" to my main page for "debugging purposes"
Is there any known Bugs for ADODB Recordsets losing records? Please keep in mind the Code is exactly the same and working "error-free".

A few suggestions.
Use Option Explicit if not already - (I didn't see it in your code) this will display SQL errors, so that may help.
Check that you haven't destroyed RS.
Also, "connection, 1, 3" means 'active connection', 'cursortype', 'locktype'
Your cursortype is 'adOpenKeySet' - 3 or 'adOpenStatic' is better, unless you specifically want a KeySet? try calling the Open this way to force the defaults (which oddly enough are 3 and 1 respectively !) :
RS.Open "SELECT * FROM tablename ORDER BY id DESC",connection
I also usually write RS output loops like this :
If Not RS.BOF Then
' write table tag HTML
Do While Not RS.EOF
' write table row + row data
RS.MoveNext
Loop
' write end table tag HTML
Else
' write "RS is empty!"
End If
This will make it easier to tell if recordset is empty or not.

Related

SQL SERVER: Loading data all at ONCE or Checking ONE by ONE?

Which one could be a better practice? In my situation, I need to check if a specific data exists in a table. I am iterating through an Excel file and verifying if a code there exists in my table using VB.NET. I have two options to do this (or if there is a better way to do this, I am open for suggestions).
First is to check it one by one, this code is executed per loop:
SQL = "SELECT TOP 1 * FROM Table1 WHERE Code = '" & codeFromExcel & "'"
rs = dbConn.Execute(SQL)
If Not rs.EOF Then
isFound = True
Else
isFound = False
End If
The other one is I load all the codes in a List(Of T)
Dim myList As New List(Of String)()
rs = Nothing
rs = dbConn.Execute("Select Code from Table1")
If Not rs.EOF Then
Do While Not rs.EOF
myList.Add(rs.Fields("Code").Value.ToString)
rs.MoveNext()
Loop
End If
Then check every record if it is in the List(Of T) while iterating in the Excel.
If myList.Contains(codeFromExcel) Then
isFound = True
Else
isFound = False
End If
I've been working with this kind of stuff most of the time and I want to know which one is the most efficient way to use. At the moment I only have a few records in my database. I want my code to be ready and efficient when the time comes that I need to deal with numerous records. Thanks in advance!
Additional info: The data doesn't need to be "fresh" as that table is meant for one-time entry only.
Personally I prefer to open as less connections to data base as possible.
So:
If the table is not very large (some hundred rows) I would go with the "cache" option.
Generally:
I would gather all excel codes in a list. ( excelCodes )
Then I would query something like Select Distinct Code from Table1 Where Code In ( excelCodesList ) and store it in a second list ( foundCodes ).
Then I would compare these lists.
I test it on a table with 6.143.993 rows.
To select just one column (description) to "cache" took 1'29".
On the other hand query like:
select distinct description from ItemDetail where description in ( 'abc','cddd','xxx' )
took 0'58".
UPDATE
An index on Code column might help with performance.

save huge xml from sql to web

In sqlserver I have a function which generates a complex xml of all products with several tables joined: location, suppliers, orders etc.
No problem in that, it runs in 68 sec and produces around 450MB.
It should only be called occationally during migration to another server, so it doesn't matter it takes some time.
I want to make this available for download over webserver.
I've tried some variations of this in classic asp:
Response.Buffer = false
set rs=conn.execute("select cast(dbo.exportXML() as varchar(max)) as res")
response.write rs("res")
But I just get a standard
An error occurred on the server when processing the URL. Please contact the system administrator.
If you are the system administrator please click here to find out more about this error.
Not my usual custom 500-errorhandler, so I'm not sure how to find the error.
The problem is in response.write rs("res"), if i just do
temp = rs("res")
the script runs, but displays nothing of cause; if I then
response.write temp
I get the same failure.
So the problem is writing such a ling string.
Can I save the file from tsql directly; and run the job periodically from sql agent?
I found that there seems to be a limit on how much data can be written at once using Response.Write. The workaround I used was to break the data into chunks like this:
Dim Data, Done
Done = False
Do While Not Done
Data = RecordSet(0).GetChunk(8192)
If Not Len(Data) = 0 Then
Response.Write Data
Else
Done = True
End If
Loop
Try this:
Response.ContentType = "text/xml"
rs.CursorLocation = 3
rs.Open "select cast(dbo.exportXML() as varchar(max)) as res",conn
'Persist the Recordset in XML format to the ASP Response object.
'The constant value for adPersistXML is 1.
rs.Save Response, 1

Records are sorted in SQL Server, but when brought to MS Access subform, the sorting is different

My query in SQL Server is sorted by several factors, and when I execute it the ordering is all correct. I have some subforms that are populated using the following code:
Set db = OpenDatabase("", False, False, globalstrSQLConnection)
strSQL = "SELECT * FROM qryTaskSimple"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot, dbSeeChanges)
Set Me.Recordset = rs
where globalstrSQLConnection is the connection to the database on my my SQL Server and qryTaskSimple is the query mentioned above. But the subforms are sorted by a completely different criterion. Instead of being sorted by:
ORDER BY CASE WHEN tblTask.JobNum LIKE '***FULL***' THEN 0 ELSE 1 END, DivisionSortID, SuperintendentSortID, ISNULL(dbo.tblTask.Ordering, 999999999),
dbo.tblTask.JobNum, dbo.tblTask.Sequence
as stated inside the query, it seems to be sorted by only tblTask.JobNum... even when I replace the entire ORDER BY clause with ORDER BY DivisionSortID... And I don't have any VBA code that further sorts the subforms.
Queries and tables in Access have an underlying query/table object order by that can over-ride the SQL order by. You can see it (and remove it) in respective object properties.
It can be pretty frustrating and I'm not really sure if that's what's going on, but regardless, you can force desired sorting by simply adding it to your SQL statement, treating the query as a table.
strSQL = "SELECT * FROM qryTaskSimple ORDER BY <your desired sorting using any qryTaskSimple cols>"
if that doesn't work, then try the (sub)forms orderby at the form's load() event:
Private Sub Form_Load()
me.orderby = "your order by statements"
if me.orderbyon = false then me.orderbyon = true
End Sub

Classic ASP Import Remote XML file into SQL Server

First off I would like to say that I think that my question may be time consuming for people to solve it in a complete sense so I understand that it is totally possible that the complete answer is asking for just way too much, so anything to help me better understand, like: reading material, examples, links, and/or advice would be great and I do very much appreciate any and every comment I receive, good or bad it just makes me and this place alot better, finally, I would like to thank you all so much for everything that you do here, this is truly a place that was build by smart people, and people that care.
MY QUESTION
(using Classic ASP and SQL Server)
I know that it is possible to read a remote XML file and then insert it into a SQL Server database table. I found one example that does that it uses Classic ASP and MS Access but that can be changed to SQL Server with minimal coding the URL is: http://forums.aspfree.com/code-bank-54/classic-asp-import-remote-xml-file-into-database-152966.html
But the problem is that I cannot get it to work on my remote XML file, I tried to edit the classic asp code (found in the link above) for days and days and I just cannot get it to work the way I would like.
So I want to start from the beginning,
The XML file in question is located on: http://www.iftach.org/taxmatrix/charts/2Q2012.xml
I seen a couple of examples on how you can export the entire xml file into the SQL Server database (like do a BULK insert, see URL: http://support.microsoft.com/kb/316005) and also on how to extract some info. from the XML but my request is kind of odd since I want to check for the Country first and then get that Counties Rate only and not the other one, I want to do this for the entire xml file.
For example the xml file is something like this:
(or you can view the full xml file by clicking on the URL above)
<FILE>
<QUARTER>2Q2012</QUARTER>
<RECORD>
<JURISDICTION ID="#15">AB</JURISDICTION>
<COUNTRY>CAN</COUNTRY>
......
......
<RATE RATECHANGE="0" COUNTRY="US">0.3366</RATE>
<RATE RATECHANGE="0" COUNTRY="CAN">0.0900</RATE>
......
......
......
</RECORD>
<RECORD>
<JURISDICTION ID="#15">FL</JURISDICTION>
<COUNTRY>U.S.</COUNTRY>
......
......
<RATE RATECHANGE="0" COUNTRY="US">1.5700</RATE>
<RATE RATECHANGE="0" COUNTRY="CAN">1.3210</RATE>
......
......
......
</RECORD>
</FILE>
and so on....
Now I would like to insert that info into the SQL Server table called FFTR and name the column specific for each JURISDICTION
Like for example the above would be:
Field Name 1 --> "JURISDICTION_AB_CAN"
Field Name 2 --> "JURISDICTION_FL_US"
and so on...
NOTE:
The prefix JURISDICTION_ will always be the same only the two letters will change and the CAN can become US.
Another thing is if the COUNTRY is "CAN" then I would like to use the CAN Rate and if it's U.S. I would like to use the US Rate and insert that info. into the database with the Field named "RATE". (The Rate will always be 4 decimal places) the Rate I want is only under: <FUEL_TYPE>Special Diesel</FUEL_TYPE> I don't need the other Rates.
And the last thing I would like to do is to have the <QUARTER>2Q2012</QUARTER> inserted into a Field named "Quarter"
So the final SQL Server database would look like this (using the 2 records as an example above)
Field Name: JURISDICTION_AB_CAN
Rate: 0.0900
Quarter: 2Q2012
Field Name: JURISDICTION_FL_US
Rate: 1.5700
Quarter: 2Q2012
So what I tried to do is this (see code below) and I got it to show each line but it doesn't even come close to a solution:
<%
Option Explicit
Response.Buffer = True
Dim xml
Set xml = Server.CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.setProperty "ServerHTTPRequest", True
xml.Load ("http://www.iftach.org/TaxMatrix/charts/2Q2012.xml")
Dim paragraph1,paragraph2,paragraph3,paragraph4,paragraph5,paragraph6
paragraph1 = xml.documentElement.childNodes(1).text
paragraph2 = xml.documentElement.childNodes(2).text
paragraph3 = xml.documentElement.childNodes(3).text
paragraph4 = xml.documentElement.childNodes(4).text
paragraph5 = xml.documentElement.childNodes(5).text
paragraph6 = xml.documentElement.childNodes(6).text
Set xml = Nothing
%>
<html>
<head>
<title></title>
</head>
<body>
<p align="center"><% = paragraph1 %></p>
<p align="center"><% = paragraph2 %></p>
<p align="center"><% = paragraph3 %></p>
<p align="center"><% = paragraph4 %></p>
<p align="center"><% = paragraph5 %></p>
<p align="center"><% = paragraph6 %></p>
</body>
</html>
I even think that adding it to a ADODB Recordset would be great and then I would insert it into SQL Server one by one or just loop it all in there, but it only shows me the columns I need the rows in there also. See code below:
<%
Dim objRS
Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = "Provider=MSDAOSP; Data Source=MSXML2.DSOControl.3.0;"
objRS.Open(Server.MapPath("2Q2012.xml"))
Response.Write(objRS.Fields(2) & "<br>") ' <-- Returns the Quarter only, that I need for the Quarter Field in the DB
'Response.Write(objRS.Fields(6) & "<br>") ' <-- Returns the entire xml page
Do While Not objRS.EOF
objRS.MoveNext
Loop
%>
<table border="1" width="100%">
<%
dim fld
Response.Write("<tr>")
For Each fld in objRS.Fields
If fld.Name <> "$Text" Then
Response.Write("<td>" & fld.Name & "</td>")
End If
Next
Response.Write("</tr>")
Do While Not objRS.EOF
Response.Write("<tr>")
For Each fld in objRS.Fields
If fld.Name <> "$Text" Then
Response.Write("<td>" & fld.Value & "</td>")
End If
Next
Response.Write("</tr>")
objRS.MoveNext
Loop
%>
</table>
Again, Thank you so much for any advice, links, or any help at all...
have a look here: msxml DOM
you should use the msxml object to read the xml. then you can query the elements of the xml by using the api.
example code for loading the xml:
<%
dim xml : set xml = server.createobject("Msxml2.DOMDocument.6.0")
dim xmlString : xmlString = getXMLHTTPResponse("http://www.iftach.org/TaxMatrix/charts/2Q2012.xml")
xml.loadxml(xmlString)
function getXMLHTTPResponse(url)
dim tout, xmlhttp
set xmlhttp = server.createObject("Msxml2.ServerXMLHTTP.6.0")
with xmlhttp
.setTimeouts 2000, 2000, 2000, 2000
.open "GET", url, false
.send()
if .responseXML.xml = "" then
getXMLHTTPResponse = .responseText
else
getXMLHTTPResponse = .responseXML.xml
end if
end with
end function
%>
Finally!!! I made it work, if anyone needs the solution it is below:
Using the code I posted in the question I added the following code:
Note: I know that this is not the best way to do it since I'm not going after the TAGS/IDs/Names but the xml file will always stay formated the same so I just Looped, Cut out what I needed, and Inserted/Updated into the DB.
<%
' LOOP ALL OF THE FIELDS ONE BY ONE
For x = 0 to xml.documentelement.childnodes.length - 1
set XMLobjchildnodes = xml.documentelement.childnodes
strXMLtxt=xml.documentElement.childNodes(x).text & "<br>"
' SETUP THE UPDATE FIELDS FOR SQL
dim strTest
strTest="objSQL(""IMP_STATE_" & Mid(strXMLtxt,1,2) & """)=" & Mid(strXMLtxt,46,7)
' SKIP THE Fi and 2Q because they are not States/Prov.
if strTest="objSQL(""IMP_STATE_Fi"")=" OR strTest="objSQL(""IMP_STATE_2Q"")=" then
else
' ALSO SKIP hi and U and CN because they also are not States/Prov.
if InStr(strTest,"STATE_ht")>0 OR InStr(strTest,"STATE_U.")>0 OR InStr(strTest,"STATE_CN")>0 then
else
' ADD YOUR SQL CONNECTION INFO. HERE AND THEN INSERT/UPDATE THE SQL DB
end if
Next
%>
Note: By making small changes you can set it to Insert the data into SQL and/or update, should this be a problem for anyone please let me know I will be more then happy to help.
To all that have tried to solve my problem/question, Thank you so much for all of your hard work and effort.

Why adParamOutput parameter doesn't contain a value after execute

I am using ASP classic with ADO, connecting to SQL Server 2008.
I inherited this code and it is so mangled that I will try to recreate the relevant parts. If you need more detail or I left something out, please let me know.
I create a command and add parameters
oCmd.CommandType = adCmdStoredProc
...
oCmd.Parameters.Append oCmd.CreateParameter("#MyOutputParam", adInteger, adParamOutput, 4, NULL)
Later, I open a reader from that command:
oRS.Open oCmd, , adOpenForwardOnly, adLockReadOnly
After that, while oRS is open but before I've read any records or values, I try to get the output parameter's value using one of the lines below:
val1 = oCmd("#MyOutputParam")
val2 = oCmd("#MyOutputParam").Value
val3 = oCmd.Parameters("#MyOutputParam").Value
All three (val1, val2, val3) variables are DB NULL.
I have confirmed that running the SP in query analyzer returns a value to the #MyOutputParam parameter:
declare #p33 int
exec usp_GetResultAndOutput 1, 2, 3, #p33 output
select #p33
That returns a recordset of my expected records and a second recordset showing a number in a single row.
I've even tried calling rs.NextRecordset before attempting to get the output parameter and that didn't work.
Is there some other way that I need to be handling Output parameters?
Is it okay that I am returning a recordset and output parameters?
Output parameters cannot be retrieved until all the recordsets are enumerated until the end. Just think, how could the client possibly retrieve the output value of a parameter before the execution finishes? The Execute() call is simply starting the execution, the batch continues to execute on the server until all results are returned. While a client is iterating over a resultset produced by a SELECT the batch is executing that SELECT. The value of the output parameter is known only at the end of the batch. Therefore is not possible to know the output parameter value until the batch finished, which implies that all statements have executed, which in turn requires that all resultsets were consumed (iterated) by the client.
This is the canonical form of parsing a set of results:
do
{
while (rs.MoveNext)
{
// do something with the row
}
} while (Not rs.NextRecordset Is Nothing)
// now is safe to read the out param
response.write oCmd("#MyOutput")
As far as I can test the only thing that matters this is the CursorLocation. As long as the CursorLocation is set to adUseClient (3), the output parameters can be accessed anytime after the Execute. Any of the following do that
oConn.CursorLocation = adUseClient
or
oRs.CursorLocation = adUseClient
This is tested on SQL 2008 R2, IIS/ASP on Windows 7 and with SQLOLEDB provider.

Resources