December 7, 2005 at 3:59 pm
Let me start by saying I am not a VB expert. I'm working with a VB developer using ADO (not .NET) that needs to return chunks of an ntext column without using GetChunk. He passes and offset and chunksize, and I return the remaining size; however, while the ntext is returned, the InputOutputParameter remains unchanged. Here's an example call:
execute GetMyText @TextID, @Offset, @Remaining output
The procedure uses a READTEXT and calculates the remaining size. In SQL Query Analyzer I would call it this way:
declare @TextID int, @Offset int, @Remaining int
select @TextID = 1, @Offset = 0, @Remaining = 1000000 output
execute GetMyText @TextID, @Offset, @Remaining output -- Returns the first chunk of Text using READTEXT
select @Remaining -- used to determine if there is more text to retrieve.
This will return a recordset of the text and the @Remaining variable will contain the expected size; however, in VB calls to ADO it doesn't change the InputOutputParameter value for the size. It always stays the same.
Is there a way to call ADO to return both the Readtext and the @Remaining output parameter?
Note: Before someone chimes in, you cannot use a variable with the readtext (i.e. @MyText = READTEXT). It violates sql syntax.
December 8, 2005 at 2:16 am
I suggest that you look at using ADODB.Stream:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdobjstream.asp
Andy
December 8, 2005 at 4:00 am
Forget ReadText. Just use SubString.
December 8, 2005 at 7:05 am
Not if the output is > 8000 bytes
The problem is due to the consumption of the output recordsets, as in the following from MSDN
"If a command returns a single result that is a recordset, output parameter data is available at the time the recordset is completely released. If a command returns multiple results, output parameter data is available when the NextRecordset method returns the next recordset or the multiple results object is completely released, whichever occurs first. Before the output parameter data is available, the consumer's bound memory is in an indeterminate state."
Therefore you need to close any recordsets before getting return and output parameters.
Far away is close at hand in the images of elsewhere.
Anon.
December 8, 2005 at 7:09 am
Agree the 8k limit but he is getting chunks so I assume that this will be ok.
December 8, 2005 at 9:52 am
Not sure if this will help you out, its VB6 not SQL but its what i use to read a Text column into a variable. you can compute the amount remaining in the while loop and process the chunk as well or snag the whole thing and process it after you have it in one variable.
VB6 using MDAC 2.8
Private Const ChunkSize As Long = 8192 ' for fetching chunks of TEXT fields from the database
Dim ProdRS As ADODB.Recordset
Dim TextSize As Long
Dim CurrentPointer As Long
Dim ProdText As String
Dim Remaining As Long
TextSize = ProdRS(YourTextColumnName).ActualSize
CurrentPointer = 0
While CurrentPointer < TextSize
ProdText = ProdText & ProdRS(YourTextColumnName).GetChunk(ChunkSize)
CurrentPointer = CurrentPointer + ChunkSize
Remaining = TextSize - CurrentPointer
' process the chunk here
Wend
Hope this helps
Bill
December 8, 2005 at 2:21 pm
Well, the chunking is occurring in 1Mb in general, so the 8K limit won't work for us. Also, we are coding to not use GetChunk. ADO.Net eliminates AppendChunk and GetChunk so we are trying to make these work as we transition the code into ADO.Net later.
David Burrows idea makes sense; however, we tried releasing the recordset (RS = Nothing) and the output parameters still do not get updated. I presume it should be automatic upon release of the recordset, correct?
December 9, 2005 at 4:23 am
I'm not entirely sure what is going on here. Could we see the stored procedure and the relevant VB, please?
December 9, 2005 at 10:10 am
we tried releasing the recordset (RS = Nothing) |
Try closing the recordset (and any additional ones if present) instead of setting it to nothing. Not sure if the recordsets need to be consumed (read) or not. I think this has to do with the number streams used by ADO and when they are processed.
Far away is close at hand in the images of elsewhere.
Anon.
December 9, 2005 at 10:21 am
I couldn't say why the output variable isn't being returned. However, would it be possible to simply select the number you want as an output variable into another record set? Once back on the VB side, you can work with your primary record set as normal, and just access the second record set as that output variable.
On the SQL side it should be pretty standard, select your record chunk as normal, the at the end of the procedure just do an extra:
SELECT remaning number size as Remaining
Back on the VB side this should be accessable as a second table in the record set. I've pretty much forgotten VB6, been using .NET for a while now (if you can, switch. It's a lot nicer.). In .NET it would look like
... (declarations, and filling a dataset)
MyData.Tables(0).However you want to access your data 'This would be your real data
Remaining = Cint(MyData.Tables(1).rows(0).item(0).ToString) 'This would get the number remaining into a convient variable
... (Whatever else you plan on doing)
December 9, 2005 at 10:47 am
I don't know if there's something special about the ntext column that's causing your problem, but here's the VB6 code I use to get a list of towns in a recordset, as well as the count of records in the recordset and the SP's return code.
<%'Working storage for stp_MileageTownsListGet
'There are no input parameters passed to the stored procedure
'These are the values returned from the stored procedure
'Move to appropriate program fields after calling stp_MileageTownsListGetExecute
dim stp_MileageTownsListGetParmValueRecordCount
dim stp_MileageTownsListGetParmValueReturnError
'if no records are returned, stp_MileageTownsListGetParmValueReturnError is changed
'from 0 to "X"
'This is the array that is built from the recordset
dim stp_MileageTownsListGetArray
'These are the column numbers for the array created from the recordset
dim stp_MileageTownsListGetTownColumn
dim stp_MileageTownsListGetColumnMax
stp_MileageTownsListGetTownColumn = 0
stp_MileageTownsListGetColumnMax = 0
%>
<!--Call this subroutine once the input parms have been supplied // -->
<% Sub stp_MileageTownsListGetExecute(substrActiveConnection, Err)
On Error Resume Next
dim cmdSubCommand
dim rsSubRecordSet
dim cnSubConnection
stp_MileageTownsListGetParmValueRecordCount = ""
stp_MileageTownsListGetParmValueReturnError = ""
stp_MileageTownsListGetArray = ""
Err.Clear
set cnSubConnection = Server.CreateObject("ADODB.Connection")
cnSubConnection.CursorLocation = adUseClient
cnSubConnection.Open substrActiveConnection
set rsSubRecordSet = Server.CreateObject("ADODB.Recordset")
rsSubRecordSet.CursorType = adOpenStatic
rsSubRecordSet.LockType = adLockReadOnly
set cmdSubCommand = Server.CreateObject("ADODB.Command")
if Err.Number > 0 then
exit sub
end if
With cmdSubCommand
.CommandType = adcmdStoredProc
.CommandText = "stp_MileageTownsListGet"
.ActiveConnection = cnSubConnection
.Parameters.Append .CreateParameter("ReturnError", adInteger, adParamReturnValue)
.Parameters.Append .CreateParameter("RecordCount",adInteger,adParamOutput)
set rsSubRecordSet = .Execute()
.ActiveConnection = nothing
stp_MileageTownsListGetParmValueRecordCount = .Parameters("RecordCount").Value
stp_MileageTownsListGetParmValueReturnError = .Parameters("ReturnError").Value
End With
if stp_MileageTownsListGetParmValueReturnError = 0 then
if stp_MileageTownsListGetParmValueRecordCount > 0 then
stp_MileageTownsListGetArray = rsSubRecordSet.GetRows(-1)
else
stp_MileageTownsListGetParmValueReturnError = "X"
end if
end if
rsSubRecordSet.Close
cnSubConnection.Close
set cmdSubCommand = nothing
set rsSubRecordSet = nothing
set cnSubConnection = nothing
End Sub%>
This is the stored procedure:
CREATE PROCEDURE stp_MileageTownsListGet
@RecordCount int output as
BEGIN
DECLARE @ReturnError int
SELECT Town1 as Town FROM TownMaster
UNION
SELECT Town2 as Town FROM TownMaster
ORDER BY Town
SELECT @RecordCount = @@RowCount, @ReturnError = @@Error
RETURN @ReturnError
END
GO
Mattie
December 11, 2005 at 3:05 pm
Can you make the Remaining parameter a field in the returned recordset?
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply