469,641 Members | 1,106 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,641 developers. It's quick & easy.

Outputting Data From Stored Procedure

Hi All

Im generally a vb programmer and am used to referencing multiple records
returned from a query performed on an sql database and im trying to move
some functions of my software into sql stored procedures. So far ive been
able to move the functions relatively easily but im unsure about how to
output multiple values from an sql stored procedure. By this i mean for
example one of the stored procedures may take your username and return the
contents of a single field in a record of one of the tables, but i would
like to be able to return for arguement sake the contents of a single field
from two records if possible. Under VB im used to referencing the recordset
with a (1) after it to reference the corresponding record from the query. I
was wondering if there is a way to do something similar to this with stored
procedures if possible ?

Thanks for any help
Jul 20 '05 #1
15 5797
Jarrod Morrison (ja*****@ihug.com.au) writes:
Im generally a vb programmer and am used to referencing multiple records
returned from a query performed on an sql database and im trying to move
some functions of my software into sql stored procedures. So far ive
been able to move the functions relatively easily but im unsure about
how to output multiple values from an sql stored procedure. By this i
mean for example one of the stored procedures may take your username and
return the contents of a single field in a record of one of the tables,
but i would like to be able to return for arguement sake the contents of
a single field from two records if possible. Under VB im used to
referencing the recordset with a (1) after it to reference the
corresponding record from the query. I was wondering if there is a way
to do something similar to this with stored procedures if possible ?


Unfortunately, without an example, I find it difficult to get a clear
understanding of what you are doing.

However, a general word of caution: SQL is a very different language
than Basic with different mindsets. Translating VB into SQL line by
line, may not always be the best approach.

Since I don't know what you are doing, this link may be completely
irrelevant. But maybe it addresses something of what you are trying to
do: http://www.algonet.se/~sommar/share_data.html.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #2
Hi Erland

Thankyou for the link, it sort of helped me a little bit, but I thought I
would give you a direct example of what I am doing to see if you can give me
any further pointers on what I can do. In my stored procedure I will execute
a query and store the results in a temporary table in the procedure. An
Example of what will be in the table is as follows:

PrinterPath Name Priority

\\Server1\Printer1 Printer 1 1
\\Server2\Printer2 Printer 2 2

What I want to do is to output only the first columns data from the
procedure to my vb client program (IE: \\Server1\Printer1 and
\\Server2\Printer2). Obviously this is a basic example and the amount of
data and records will change all the time. To begin with I only want to
output the first column, but if possible down the track I would also like to
do multiple columns if it is possible. At the moment in my other stored
procedures I am just defining a variable at the beginning of the procedure
as output and assigning a value to it before the procedure ends. I am hoping
there is an easy way to output multiple values from the stored procedure in
a similar fashion.

Thanks for all your help

"Erland Sommarskog" <so****@algonet.se> wrote in message
news:Xn*********************@127.0.0.1...
Unfortunately, without an example, I find it difficult to get a clear
understanding of what you are doing.

However, a general word of caution: SQL is a very different language
than Basic with different mindsets. Translating VB into SQL line by
line, may not always be the best approach.

Since I don't know what you are doing, this link may be completely
irrelevant. But maybe it addresses something of what you are trying to
do: http://www.algonet.se/~sommar/share_data.html.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Jul 20 '05 #3
Jarrod Morrison (ja*****@ihug.com.au) writes:
Example of what will be in the table is as follows:

PrinterPath Name Priority

\\Server1\Printer1 Printer 1 1
\\Server2\Printer2 Printer 2 2

What I want to do is to output only the first columns data from the
procedure to my vb client program (IE: \\Server1\Printer1 and
\\Server2\Printer2). Obviously this is a basic example and the amount of
data and records will change all the time. To begin with I only want to
output the first column, but if possible down the track I would also
like to do multiple columns if it is possible.


SELECT PrinterPath FROM tbl WHERE ...

SELECT PrinterPath, Name FROM tbl WHERE ...

Then in VB you receive the values in a recordset.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #4
Hi Erland

Do you mean to do the select statement straight from the vb program ? Or
just plain do the select statement in the stored procedure on the sql server
and vb program will receieve it as a recordset ? I dont really understand
what you meant there as i was trying to do all the work in the sql stored
procedure if possible and just return the results

Thanks
"Erland Sommarskog" <so****@algonet.se> wrote in message
news:Xn**********************@127.0.0.1...
Jarrod Morrison (ja*****@ihug.com.au) writes:
Example of what will be in the table is as follows:

PrinterPath Name Priority

\\Server1\Printer1 Printer 1 1
\\Server2\Printer2 Printer 2 2

What I want to do is to output only the first columns data from the
procedure to my vb client program (IE: \\Server1\Printer1 and
\\Server2\Printer2). Obviously this is a basic example and the amount of
data and records will change all the time. To begin with I only want to
output the first column, but if possible down the track I would also
like to do multiple columns if it is possible.


SELECT PrinterPath FROM tbl WHERE ...

SELECT PrinterPath, Name FROM tbl WHERE ...

Then in VB you receive the values in a recordset.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Jul 20 '05 #5
Jarrod Morrison (ja*****@ihug.com.au) writes:
Do you mean to do the select statement straight from the vb program ? Or
just plain do the select statement in the stored procedure on the sql
server and vb program will receieve it as a recordset ? I dont really
understand what you meant there as i was trying to do all the work in
the sql stored procedure if possible and just return the results


I was thinking of something like:

CREATE PROCEDURE your_sp AS
SELECT PrinterPath, Name FROM tbl WHERE...

I'm sorry if my answers are not fully clear, but I have a feeling that
there something hiding in your questions that I have not been able to
grasp.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #6
Hi

This is my interpretation
By this i
mean for example one of the stored procedures may take your username and
return the contents of a single field in a record of one of the tables,
1 - You have a fixed number of output parameters from the stored
procedure

Dim objConn as ADODB.Connection
Dim objCmd As ADODB.Command
Dim objRst As ADODB.Recordset
Dim objField As ADODB.Field

'Open your connection first

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)
objCmd.Parameters.Append objCmd.CreateParameter("Father",
adVarChar, adParamOutput, 50)
objCmd.Parameters.Append objCmd.CreateParameter("Mother",
adVarChar, adParamOutput, 50)

'Execute
objCmd.Execute

'Get your parameters back out
strFather = objCmd.Parameters("Father").Value
strMother = objCmd.Parameters("Mother").Value

2 - You need to retrieve a number of records from one field.
but i would like to be able to return for arguement sake the contents of
a single field from two records if possible. Under VB im used to
referencing the recordset with a (1) after it to reference the
corresponding record from the query. I was wondering if there is a way
to do something similar to this with stored procedures if possible ?

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)

'Execute
Set objRst = objCmd.Execute

'Get the field. For large recordsets, this is the best approach
'See http://www.vb2themax.com/Item.asp?PageID=TipBank&ID=265
'You can use (1) here if you'd like
'Set objField = objRst.Fields(1)
Set objField = objRst.Fields("YourField")

'Get your values from the recordset
Do Until objRst.EOF
Debug.Print objField.Value
objRst.MoveNext
Loop

objRst.Close
Set objRst = Nothing
I hope this is what you're looking for
Jul 20 '05 #7
Hi Samuel

Thanks for the post, thats exactly what i wanted. But i have one further
question about the second part of the post, when i execute the select
statement inside the stored procedure it is actually part of a loop and thus
each select statement is being treated seperately by VB, so if i use query
analyzer i see for example 3 seperate returns which is ok because it is what
is meant to be returned, however vb is only reading the first one of these
returns and then closing the recordset. Im sure there is an easy way around
this but im unsure of what to do. Any help is greatly appreciated

Thanks

"Samuel Hon" <no*****@samuelhon.co.uk> wrote in message
news:c8**************************@posting.google.c om...
Hi

This is my interpretation
By this i
mean for example one of the stored procedures may take your username and
return the contents of a single field in a record of one of the tables,


1 - You have a fixed number of output parameters from the stored
procedure

Dim objConn as ADODB.Connection
Dim objCmd As ADODB.Command
Dim objRst As ADODB.Recordset
Dim objField As ADODB.Field

'Open your connection first

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)
objCmd.Parameters.Append objCmd.CreateParameter("Father",
adVarChar, adParamOutput, 50)
objCmd.Parameters.Append objCmd.CreateParameter("Mother",
adVarChar, adParamOutput, 50)

'Execute
objCmd.Execute

'Get your parameters back out
strFather = objCmd.Parameters("Father").Value
strMother = objCmd.Parameters("Mother").Value

2 - You need to retrieve a number of records from one field.
but i would like to be able to return for arguement sake the contents of
a single field from two records if possible. Under VB im used to
referencing the recordset with a (1) after it to reference the
corresponding record from the query. I was wondering if there is a way
to do something similar to this with stored procedures if possible ?

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)

'Execute
Set objRst = objCmd.Execute

'Get the field. For large recordsets, this is the best approach
'See http://www.vb2themax.com/Item.asp?PageID=TipBank&ID=265
'You can use (1) here if you'd like
'Set objField = objRst.Fields(1)
Set objField = objRst.Fields("YourField")

'Get your values from the recordset
Do Until objRst.EOF
Debug.Print objField.Value
objRst.MoveNext
Loop

objRst.Close
Set objRst = Nothing
I hope this is what you're looking for

Jul 20 '05 #8
Hi Erland

Thanks for all your help with the stored procedure questions, Samuel replied
to the posts as well and gave me a good vb example to go with and now it
seems like it is all working well. Thanks again

"Erland Sommarskog" <so****@algonet.se> wrote in message
news:Xn**********************@127.0.0.1...
Jarrod Morrison (ja*****@ihug.com.au) writes:
Do you mean to do the select statement straight from the vb program ? Or
just plain do the select statement in the stored procedure on the sql
server and vb program will receieve it as a recordset ? I dont really
understand what you meant there as i was trying to do all the work in
the sql stored procedure if possible and just return the results


I was thinking of something like:

CREATE PROCEDURE your_sp AS
SELECT PrinterPath, Name FROM tbl WHERE...

I'm sorry if my answers are not fully clear, but I have a feeling that
there something hiding in your questions that I have not been able to
grasp.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Jul 20 '05 #9
Not sure I understand your question exactly, but it sounds like maybe
you need the ADO .NextRecordset method, which does just what it sounds
like, brings back the next recordset from your stored procedure.

On Sun, 14 Dec 2003 16:01:21 +1100, "Jarrod Morrison"
<ja*****@ihug.com.au> wrote:
Hi Samuel

Thanks for the post, thats exactly what i wanted. But i have one further
question about the second part of the post, when i execute the select
statement inside the stored procedure it is actually part of a loop and thus
each select statement is being treated seperately by VB, so if i use query
analyzer i see for example 3 seperate returns which is ok because it is what
is meant to be returned, however vb is only reading the first one of these
returns and then closing the recordset. Im sure there is an easy way around
this but im unsure of what to do. Any help is greatly appreciated

Thanks

"Samuel Hon" <no*****@samuelhon.co.uk> wrote in message
news:c8**************************@posting.google. com...
Hi

This is my interpretation
> By this i
> mean for example one of the stored procedures may take your username and
> return the contents of a single field in a record of one of the tables,


1 - You have a fixed number of output parameters from the stored
procedure

Dim objConn as ADODB.Connection
Dim objCmd As ADODB.Command
Dim objRst As ADODB.Recordset
Dim objField As ADODB.Field

'Open your connection first

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)
objCmd.Parameters.Append objCmd.CreateParameter("Father",
adVarChar, adParamOutput, 50)
objCmd.Parameters.Append objCmd.CreateParameter("Mother",
adVarChar, adParamOutput, 50)

'Execute
objCmd.Execute

'Get your parameters back out
strFather = objCmd.Parameters("Father").Value
strMother = objCmd.Parameters("Mother").Value

2 - You need to retrieve a number of records from one field.
> but i would like to be able to return for arguement sake the contents of
> a single field from two records if possible. Under VB im used to
> referencing the recordset with a (1) after it to reference the
> corresponding record from the query. I was wondering if there is a way
> to do something similar to this with stored procedures if possible ?

'Open command
Set objCmd = New ADODB.Command
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "spGetParents"
Set objCmd.ActiveConnection = objConn

'Add your input and output parameters
objCmd.Parameters.Append objCmd.CreateParameter("UserName",
adVarChar, adParamInput, 8, strUserName)

'Execute
Set objRst = objCmd.Execute

'Get the field. For large recordsets, this is the best approach
'See http://www.vb2themax.com/Item.asp?PageID=TipBank&ID=265
'You can use (1) here if you'd like
'Set objField = objRst.Fields(1)
Set objField = objRst.Fields("YourField")

'Get your values from the recordset
Do Until objRst.EOF
Debug.Print objField.Value
objRst.MoveNext
Loop

objRst.Close
Set objRst = Nothing
I hope this is what you're looking for


Jul 20 '05 #10
Jarrod Morrison (ja*****@ihug.com.au) writes:
Thanks for the post, thats exactly what i wanted. But i have one further
question about the second part of the post, when i execute the select
statement inside the stored procedure it is actually part of a loop and
thus each select statement is being treated seperately by VB, so if i
use query analyzer i see for example 3 seperate returns which is ok
because it is what is meant to be returned, however vb is only reading
the first one of these returns and then closing the recordset. Im sure
there is an easy way around this but im unsure of what to do. Any help
is greatly appreciated


As Ellen K said, you can use .NextRecordset to access the remaining
recordsets.

However, you should probably redesign your stored procedure. First of
all, maybe you don't need that loop. There are situations when you
need to run loops in T-SQL, but programmers who are used to VB, C and
the like but are not well versed in SQL, tend to use loops far more
often than they need. There can be a huge performance gain in replacing
a loop with set-based processing.

But even if you cannot replace the loop, you should probably not return
data for each turn in the loop. Not only does it make you VB processing
more complicated, but it is also ineffecient in regards to network
resources. Rather than returning data to the client, you can insert
the data into a table variable or a temp table, and then have a SELECT
at the end of the loop that returns data from the temp table.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #11
Erland Sommarskog <so****@algonet.se> wrote in message news:<Xn**********************@127.0.0.1>...
Jarrod Morrison (ja*****@ihug.com.au) writes:
Thanks for the post, thats exactly what i wanted. But i have one further
question about the second part of the post, when i execute the select
statement inside the stored procedure it is actually part of a loop and
thus each select statement is being treated seperately by VB, so if i
use query analyzer i see for example 3 seperate returns which is ok
because it is what is meant to be returned, however vb is only reading
the first one of these returns and then closing the recordset. Im sure
there is an easy way around this but im unsure of what to do. Any help
is greatly appreciated


As Ellen K said, you can use .NextRecordset to access the remaining
recordsets.

However, you should probably redesign your stored procedure. First of
all, maybe you don't need that loop. There are situations when you
need to run loops in T-SQL, but programmers who are used to VB, C and
the like but are not well versed in SQL, tend to use loops far more
often than they need. There can be a huge performance gain in replacing
a loop with set-based processing.

But even if you cannot replace the loop, you should probably not return
data for each turn in the loop. Not only does it make you VB processing
more complicated, but it is also ineffecient in regards to network
resources. Rather than returning data to the client, you can insert
the data into a table variable or a temp table, and then have a SELECT
at the end of the loop that returns data from the temp table.


I've never found a need to use .NextRecordset yet. As Erland says,
better stored procs are the way forward. Have you got a sample loop
that you can post?
Jul 20 '05 #12
Samuel Hon (no*****@samuelhon.co.uk) writes:
I've never found a need to use .NextRecordset yet. As Erland says,
better stored procs are the way forward. Have you got a sample loop
that you can post?


You haven't? For me whose favourite client library i DB-Library, it
seems obvious that you should use .NextRecordset. There may not be
any more recordsets to pick up, if there is and you don't get them,
you can run into surprises. (With DB-Lib and ODBC you will get an error
on next access. ADO will open a new connection, but that may still lead
to unexpected behaviour.)

A presumption for ditching .NextRecordset completely is that you use
SET NOCOUNT ON consistently.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #13
I've actually never used it either... but I know it exists. :)

On 15 Dec 2003 01:53:29 -0800, no*****@samuelhon.co.uk (Samuel Hon)
wrote:
I've never found a need to use .NextRecordset yet.


Jul 20 '05 #14
Hi Erland

Well i did at first attempt to insert all the data into a temporary table in
sql, and at the end say select * from #tablename, but when i try to access
the data from the vb program i recieve the error

Runtime error 3265

Item cannot be found in the collection corresponding to the requested name
or ordinal

I am using the example that samuel posted previously as the basis for my
coding and it returns data correctly if i do select statements on non
temporary sql tables fine but when it is on a temporary table i recieve the
above error. Below is the stored procedure i am working on

CREATE PROCEDURE [dbo].[TestProcedure01]

@EntityLocationID VarChar(300)

AS

DECLARE @SrchCount VarChar(3) /* Search Loop Count */
DECLARE @SrchInt VarChar (3) /* Current Search Position */

SET @SrchInt = 1
SET @SrchCount = (LEN(@EntityLocationID) - 1) / 3

CREATE TABLE #AvailPrint (Path VarChar(60), Name VarChar(30), Priority
Char(1), LocationID VarChar(300))

WHILE @SrchInt <= @SrchCount

BEGIN
INSERT INTO #AvailPrint(Path,Name,Priority,LocationID) SELECT *
FROM Printers WHERE LocationID LIKE RIGHT(LEFT(@EntityLocationID,
@SrchInt * 3 + 1),3)
/*SELECT * FROM Printers WHERE LocationID LIKE
RIGHT(LEFT(@EntityLocationID, @SrchInt * 3 + 1),3)*/
SET @SrchInt = @SrchInt + 1
END

SELECT * FROM #AvailPrint
GO

What this procedure does at the moment is to pull out 3 records from a table
and place them into the temporary table (The number of records is not fixed
and is dependant on the input variable @EntityLocationID), nd it outputs a
table in query analyzer fine. If i change the procedure so that the INSERT
INTO line is remarked out (Put a /* */ around it) and remove the remarks on
the line below the query analyzer returns the 3 records but they are
seperated, so when i use the vb program i am only able to access the first
record of data. Im not sure how to structure the procedure without the loop
as im used to using vb loops so any help with this is greatly appreciated

Thanks
Jul 20 '05 #15
Jarrod Morrison (ja*****@ihug.com.au) writes:
Well i did at first attempt to insert all the data into a temporary
table in sql, and at the end say select * from #tablename, but when i
try to access the data from the vb program i recieve the error

Runtime error 3265

Item cannot be found in the collection corresponding to the requested name
or ordinal

I am using the example that samuel posted previously as the basis for my
coding and it returns data correctly if i do select statements on non
temporary sql tables fine but when it is on a temporary table i recieve
the above error. Below is the stored procedure i am working on


The error message is from Visual Basic, and means that the index you
are using to address a collection is not valid.

I would guess tha the reason is that one or more of the columns in
the temp table, does have the same name as the colunms in the
Printers table, but you have failed to amend the VB code for this.

Permit me to note, that I would not have to resort to guessing, if
you also had included the VB code you are using, and you had replace
SELECT * FROM Printers with the actual columns. In my opinion,
"SELECT *" from permanent tables should not be used in stored
procedures, because the procedure could break if someone adds a new
column to the table. (From this follows that SELECT * from the temp
table is OK.)

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by pmud | last post: by
6 posts views Thread by Wojciech Wendrychowicz | last post: by
3 posts views Thread by David Lozzi | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.