关于从存储过程中取数的问题

fyming 2015-05-18 10:20:04
Dim conn As SqlConnection
Dim cmd As SqlCommand
Dim myReader As SqlDataReader
Dim myPrm As SqlParameter()

Dim lngRows As Long
Dim lngErrCode As Long

Dim i As Integer, j As Integer

conn = New SqlConnection(connDbStr)
conn.Open()

cmd = New SqlCommand("test", conn)
With cmd
.CommandType = CommandType.StoredProcedure
.CommandTimeout = 0
.Connection = conn

.Parameters.Add("@v", SqlDbType.Int).Value = 1

.Parameters.Add("@lngErrCode", SqlDbType.Int)
.Parameters("@lngErrCode").Direction = ParameterDirection.Output
.Parameters.Add("@Rows", SqlDbType.Int)
.Parameters("@Rows").Direction = ParameterDirection.Output

End With
----------------------------------------------------------------
上面代码表示打开SQL SERVER的一个存储过程test,三个参数:@v,@lngErrCode和@Rows,其中@lngErrCode和@Rows需要返回值

目的:我想要该存储过程将返回一个纪录集和两个参数@lngErrCode和@Rows,看下面代码:

'-------返回值-----------------------------
i = cmd.ExecuteNonQuery
lngErrCode = cmd.Parameters("@lngErrCode").Value
lngRows = cmd.Parameters("@Rows").Value

'-------获取数据集----------------------------
myReader = cmd.ExecuteReader()
myReader.Read()
……

现在的问题是:
i = cmd.ExecuteNonQuery

myReader = cmd.ExecuteReader()

不是要两次打开数据库吗?能不能打开一次数据就把参数返回值和纪录集都抓取过来呢?这在VB6时代不是问题,但在VB.net中我不知怎么写了,兄弟们帮忙看看
...全文
282 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ckp00001 2015-05-24
  • 打赏
  • 举报
回复
你不就是要一个返回的 记录行数吧: Dim T As New DataTable myReader = cmd.ExecuteReader() T.Load(myReader) ' T.rows.count 是你要的记录行数
fyming 2015-05-20
  • 打赏
  • 举报
回复
引用 10 楼 Tiger_Zhao 的回复:
说人话!!! 如果要返回记录集,必定要遍历Reader。不遍历哪来的记录集?
文明点,兄弟 我是要把纪录集通过数组的方式返还给前台,在把纪录集赋给数组之前不先得REDIM数组吗?你不知道纪录集行数你怎么REDIM数组?要想获得纪录集行数无非两个方法:本地遍历Reader累加获得或者直接把远程数据库端取数时产生的@@ROWCOUNT以OUTPUT参数形式直接获得。我就是不想采用本地遍历Reader累加获得这种效率低的方法才针对第二种方法提出问题。这在VB6中根本就不是问题,我都是这么做的。现在我是想在VB.NET中重写一下,我想在VB6中能做的,没理由在VB.NET中反而不能实现了吧?只是我不熟悉VB.NET的语法,不知道怎样写而已。 不懂不要紧,没人怪你,看别人怎样回答就是了,不要做喷子。
Tiger_Zhao 2015-05-20
  • 打赏
  • 举报
回复
说人话!!!
如果要返回记录集,必定要遍历Reader。不遍历哪来的记录集?
fyming 2015-05-20
  • 打赏
  • 举报
回复
引用 13 楼 Z65443344 的回复:
不要满脑子数组 你查询数据库为什么要放数组里? 放list<string>里也比放string[]里要强的多 啊
你说的当然有道理啊,但那是另外一个问题。 我现在是要对以前的一个VB6程序做升级,只能是数组。这只是就事论事而已。
於黾 2015-05-20
  • 打赏
  • 举报
回复
不要满脑子数组 你查询数据库为什么要放数组里? 放list<string>里也比放string[]里要强的多 啊
Tiger_Zhao 2015-05-20
  • 打赏
  • 举报
回复
VB6中记录集是RecordSet,转VB.Net最接近的是DataTable。
你的DataTable在哪里?
口口声声要按VB6的方式做,转出来的却完全不对应!

我们生活在不同的次元,这里逻辑没法沟通了。
你觉得这是你那个次元的人话,我无话可说。
END
Tiger_Zhao 2015-05-19
  • 打赏
  • 举报
回复
只要 ExecuteReader() 就可以。
        myReader = cmd.ExecuteReader()
While myReader.Read()
...
End While
myReader.Close()
' 注:必须在 SqlDataReader.Close() 后才能取 OUTPUT 参数
lngErrCode = cmd.Parameters("@lngErrCode").Value
lngRows = cmd.Parameters("@Rows").Value
fyming 2015-05-19
  • 打赏
  • 举报
回复
引用 8 楼 Tiger_Zhao 的回复:
只要 ExecuteReader() 就可以。
        myReader = cmd.ExecuteReader()
        While myReader.Read()
            ...
        End While
        myReader.Close()
        ' 注:必须在 SqlDataReader.Close() 后才能取 OUTPUT 参数
        lngErrCode = cmd.Parameters("@lngErrCode").Value
        lngRows = cmd.Parameters("@Rows").Value
这样会有个问题,@Rows(即纪录集行数)在 While myReader.Read() ... End While 时还没被赋值,无法把纪录集作为数组回传。当然可以用遍历myReader的方法来得到这个值,但这毕竟又多了一道开销,也失去了在数据库里返回@Rows的意义 如果能够在 While myReader.Read()之前就得到@Rows,目的就可以达到了,兄弟们再帮忙看看
  • 打赏
  • 举报
回复
这应该是由于SqlReader的特殊机制导致的,它是保持连接,连接向后读取的,而不是像datatset那样直接填充到内存表 两个办法: 改成用sqlAdapter.Fill(dataSet) 或者改存储过程 说实施,个人比较反感存储过程中用EXEC SP_EXECUTESQL执行,容易产生注入bug
BEGIN
SELECT * FROM employee
--也可以返回两个结果集,用dataset获取结果
--SELECT @@ROWCOUNT AS ROWS,  CASE WHEN @@ERROR=0 THEN 0 ELSE 1 END AS lngErrCode
SET @Rows=@@ROWCOUNT
      IF @@ERROR<>0 
                SET @lngErrCode=1
      Else
                SET @lngErrCode=0
       End
END
Tiger_Zhao 2015-05-18
  • 打赏
  • 举报
回复
myReader.HasRows 和 myReader.Read() 都能知道有没有记录。
myReader.Read() 遍历一遍就知道记录数了,为什么要 ExecuteNonQuery?
fyming 2015-05-18
  • 打赏
  • 举报
回复
引用 3 楼 dongxinxi 的回复:
只需要myReader = cmd.ExecuteReader()就可以了 i = cmd.ExecuteNonQuery会忽略返回的数据集
经测试,如果没有 cmd.ExecuteNonQuery,那么就得不到@Rows的返回值 我既想要纪录集,也同时想得到参数的返回值,怎么办?
  • 打赏
  • 举报
回复
只需要myReader = cmd.ExecuteReader()就可以了 i = cmd.ExecuteNonQuery会忽略返回的数据集
fyming 2015-05-18
  • 打赏
  • 举报
回复
下面是我数据库端存储过程代码: ------------------------------------------------------- CREATE PROCEDURE [dbo].[TEST] @v INT, @lngErrCode INT=NULL OUTPUT, @Rows INT=NULL OUTPUT --------------------------------------------------------------- --WITH ENCRYPTION AS SET NOCOUNT ON DECLARE @SQL NVARCHAR(MAX) IF @v=1 BEGIN SELECT @lngErrCode=0 SET @SQL=N'SELECT * FROM employee'+N' SET @Rows=@@ROWCOUNT' --PRINT @SQL EXEC SP_EXECUTESQL @SQL,N'@Rows INT OUTPUT',@Rows OUTPUT IF @@ERROR<>0 SET @lngErrCode=1 END ------------------------------------------------------------------------- 目的就是: 1、返回前台应用程序参数:@lngErrCode和@Rows的值 2、返回SELECT * FROM employee'
於黾 2015-05-18
  • 打赏
  • 举报
回复
cmd.Parameters 有类型啊,分input和output 你把结果output出来啊,而不是存储过程将结果写入临时表,然后再去临时表里查询
fyming 2015-05-18
  • 打赏
  • 举报
回复
引用 5 楼 Tiger_Zhao 的回复:
myReader.HasRows 和 myReader.Read() 都能知道有没有记录。 myReader.Read() 遍历一遍就知道记录数了,为什么要 ExecuteNonQuery?
不仅仅是纪录数的问题,我只是打个比方。我的意思是,我希望一次性将存储过程里的纪录集和参数都返回到前台(假设该存储过程既执行了一个查询,同时又产生了多个 OUTPUT类型的参数返回值)。这种情况下,前台采用SqlDataReader方式获 取数据好象有问题,它只能抓取纪录集,但不能抓取参数返回值,如果要想抓取参数返回值,还必须得cmd.ExecuteNonQuery,这样一来,不就是两次打开数据库了吗?效率低。

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧