When I perform a SQL Query through MS Access I get results returned but if I perform the same query in VBScript my RecordCount is -1. I can't tell if this is a connection error. I'm not getting any but it's clear that the SQL does return results in Access. I'm getting 0 hits in the below connect code.
sqlquery = "SELECT * FROM i2cner WHERE Authors Like 'Ish*';"
dim conn
set conn=Server.CreateObject("ADODB.Connection")
conn.Provider="Microsoft.Jet.OLEDB.4.0"
conn.Open "d:/inetpub/ga/sarina/i2cner/contacts2000.mdb"
set r = Server.CreateObject("ADODB.recordset")
if r.state = 1 then r.close
r.Open sqlquery, conn
hits = r.RecordCount
session("hits") = hits
set session("r") = r
r.CursorLocation = 3 'adUseClient. Thanks #HansUp
Add the above line before using r.Open.
The CursorLocation is adUseServer. As a result, records are fetched as you progress (similar to .net datareader). Changing it to adUseClient will bring all records on the client side, which will give correct RecordCount.
EDIT: Also, it isn't meaningful to store recordset in session. And, you should close the connection once you are done using it -
conn.Close
set conn = Nothing
What is the need to store recordset in session?
If you just need the number of record counts then you can give
sqlquery = "SELECT COUNT(*) AS cnt FROM i2cner WHERE Authors LIKE 'Ish%'"
Note that there is no ; in the SQL string.
When you have to retrieve the count, you can just have
hits = r.fields("cnt")
OR
hits = r("cnt")
Recordcount is sometimes deceptive, so I don't use it much. I use the above approach every time.
Related
Can I do aggregation query for a recordset in VBA. the first part code is the following:
'' part 1
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Open the connection and execute.
conn.Open sConnString
Set rs = conn.Execute("SELECT * FROM Table1;") ''' this SQL Statement is a simplified one;the actual one is very complex.
RS will be display in sheet 1; then I want to display the result of the following in sheet2:
select sum(col1), count(*), sum(col2) from
(select * from table1) group by 1,2 order by 1,2
because rs has been got from the database in part 1, I does not want to re-run the SQL in database, instead I want to get the result of part 2 in VBA's recordset.
I check the method of recordset, it only provides the method of count, move,etc.
Anyone can help me? thanks!
I'm trying to read from different Tables on a Oracle Database using VBA and Excel.
Usually when read the tables I run something like:
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
Dim query As String: query = "SELECT * FROM OBJ_NAME"
rs.Open query, con
However, this does not work for all the tables. Using SQL Developer i usually run at the beginning:
exec session#.open_session();
After which I can read any table. Is there a way to run this command with an ADODB.Recordset in the beginning too? Just replacing the SQL Query with the command did not work.
Or is there different way to read this 'hidden' Tables?
Try something like that:
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
Dim query As String: query = "begin session#.open_session; end;"
With rs
.ActiveConnection = con
.Open query, con
End With
Set connectToDB = con
This should work using VBA. Let me if it worked :)
I have a pretty basic execution of a stored procedure in my code:
Dim objCmd As ADODB.Command
Dim objConn As ADODB.Connection
Dim rsTemplate As ADODB.Recordset
Set objConn = New ADODB.Connection
objConn.Open strConnection
Set objCmd = New ADODB.Command
objCmd.ActiveConnection = objConn
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "GetTemplate"
objCmd.Parameters.Append objCmd.CreateParameter("#Param1", adInteger, adParamInput, , lngParam1)
objCmd.Parameters.Append objCmd.CreateParameter("#Param2", adInteger, adParamInput, , lngParam1)
objCmd.CommandTimeout = 600
Set rsTemplate = objCmd.Execute()
LogInfo "Found " & rsTemplate.RecordCount & " templates"
The SP is supposed to find a single row. The problem is that sometimes it fines none, which is actually okay, except that the RecordCount property is -1 in both cases. I would have expected 0 for zero records and 1 for one record. I have another section of code that can return a single or multiple rows, and with my testing parameters, it is returning seven rows, and RecordCount is correctly showing 7. Does anyone know why I'm getting inconsistent results? I need to be able to skip a subsequent piece of code if I get zero results here, and there's no other good way to check, other than trying to access a bad RecordSet object and having a special handler to resume next if it's a particular error code.
If your strConnection is such that you are specifiying a forward-only cursor, then the record count will always be -1 as the result-size cannot be identified with that kind of connection.
From here http://msdn.microsoft.com/de-de/library/windows/desktop/ms676701(v=vs.85).aspx
The cursor type of the Recordset object affects whether the number of
records can be determined. The RecordCount property will return -1 for
a forward-only cursor; the actual count for a static or keyset cursor;
and either -1 or the actual count for a dynamic cursor, depending on
the data source.
Make sure in your stored procedure GetTemplate, you have enabled the row count.
Example:
CREATE procedure [dbo].[GetTemplate]
AS
BEGIN
SET NOCOUNT OFF -- Enable row count here
...
END
dim FindRecordCount as integer
If rsTemplate.EOF Then
FindRecordCount = 0
Else
rsTemplate.MoveLast
FindRecordCount = rstRecords.AbsolutePosition
End If
Maybe you can try something like this
What I am trying to do is to get some data from an online server through an SQL Query and then loop through the recordset modifying the records.
I get an error when trying to modify the recordset:
"Multiple-Step operation generated errors. Check each status value."
My question is: Is there a way of modifying a record from a recordset that I got from a Query?
In this case I am modifying field 2 if field 1 meets a certain criteria. (In this case Field 2 is a string)
Here is the simplified code:
Dim adoConn As ADODB.Connection
Dim locRS As New ADODB.Recordset, proRS As ADODB.Recordset
Dim strConnection As String
Set getSQL = New ADODB.Recordset
'Set Objects
Set adoConn = New ADODB.Connection
'Specify connection string
strConnection = "User ID=xxx; Password=xxx;Data Source=xxx;Provider=OraOLEDB.Oracle"
'Open the connection
adoConn.Open (strConnection)
'Set up recordset properties
getSQL.CursorType = adOpenStatic
getSQL.CursorLocation = adUseClient
getSQL.LockType = adLockBatchOptimistic
'Import the data
getSQL.Open "SELECT FIELD1, FIELD2 FROM TABLE", adoConn, adOpenStatic, adLockOptimistic
Set getSQL.ActiveConnection = Nothing
getSql.Update
'Loop through data
getSQL.MoveFirst
Do While Not stockRS.EOF
'If cetrain condition is met then modify the null column
if getSQL!FIELD1=CRITERIA then
'Error here
getSQL!FIELD2="SOME STRING"
End If
getSQL.MoveNext
Loop
'Close
adoConn.Close
Set adoConn = Nothing
Your SQL is not doing what you think:
SELECT ... NULL OUTCOME ... is going to return the value NULL in a field called OUTCOME but will not link to a field in the table called OUTCOME (which is what I think you are looking for) as your current syntax is setting up an ALIAS not selecting the field. I am assuming the field OUTCOME exists on the table. If not you need to create it up front or do an alter table to add the field before you can write anything to it.
I recommend creating field up front (which I think you have already done). But make sure that the default value is NULL so you don't need to do your NULL trick in the select ALSO make sure that the field is allowed to take a NULL value or you will see errors. Select becomes:
getSQL.Open "SELECT FIELD1, FIELD2, OUTCOME FROM TABLE", adoConn, adOpenStatic, adLockOptimistic
And then manage the NULL value in the function as follows:
if getSQL!FIELD1=CRITERIA then
'Error here
getSQL!OUTCOME="SOME STRING"
ELSE
getSQL!OUTCOME=NULL
End If
This ensure that you always write something to OUTCOME field so processing and OUTCOME don't get out of sync.
Also I still think that you have divorced the recordset data from the server when you:
Set getSQL.ActiveConnection = Nothing
Do this to release resources after your are done.
You may also need a
getSql.Update
After making changes to commit them back to database.
In my classic asp app, I am calling a stored procedure and it is supposed to get me a record set through a select statement. If I try the stored procedure select statement in the sql management studio, I get like 100 rows, but when I try calling it in class asp code, I get a record set that has a record count of -1.
Does anyone know why this could be happening?
Thanks.
EDIT :
Dim Conn
SET rsGetHireID = Server.CreateObject("ADODB.RecordSet")
SET Conn = Server.CreateObject("ADODB.Command")
Conn.CommandText = "sp_selectNewHireSQL"
Conn.CommandType = adCmdStoredProc
Conn.ActiveConnection = ConnectionString
Set rsGetHireID = Conn.Execute
NumOfHireID = rsGetHireID.RecordCount
Response.Write (NumOfHireID)
OLD working code:
newHireSQL = "select * from NewHire where Archived = 0 order by HireID desc"
Set rsGetHireID = Server.CreateObject("ADODB.Recordset")
rsGetHireID.Open newHireSQL,ConnectionString,adOpenStatic
NEW EDIT:
It seems the fix was to remove the BEGIN and END from the stored procedure, which was causing a loop.
I am pretty sure that your problem is the type of cursor you are opening on your recordset. Not all of them support the recordcount property.
From MSDN
Use the RecordCount property to find out how many records are in a
Recordset object. The property returns -1 when ADO cannot determine
the number of records or if the provider or cursor type does not
support RecordCount. Reading the RecordCount property on a closed
Recordset causes an error.
To specify the cursor type you will need to use the open method on the recordset object.
'use CursorType=3 (Static)
rsGetHireID .Open CommandObjectOrSQLQuery, Conn , CursorType
the easy way you may use..
1.rsGetHireID.open newHireSQL,Conn,1,3
Thanx
Remove the BEGIN and END that the stored procedure template puts by default. Having those causes a loop.