在itpub论坛里提了一个问题:“用 ref cursor 返回结果集时可以同时得到记录个数么?不用查count(*),也不用 loop fetch 后再查 cursor%rowcount。”没有人回复。如果用 select count(*) 来获得 rowcount,则要多进行一次查询;用 loop fetch 循环计数也可以,但都感觉不好。既然得到了结果集,那么其记录个数应该就是固定的,为什么还要单查一次呢?
在网上搜了一下,单从 Oracle 数据库没有什么好办法。oracle并不是一次提取出全部的结果集的,因此要获得一个结果集的总数,只能做两次,一次打开cursor or ref cursor;第二次来个循环fetch。如果是查询一个表的总数,只能使用count函数才能获得总数,而不是%rowcount。
但是通过外部调用程序的属性或方法应该可以做到。如asp 里用 rs.recodecount,源代码如下:
<!-- #include file="adovbs.inc" -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>test</title>
<link href="../css/font.css" rel="stylesheet" type="text/css">
</head>
<body>
<%
datecreated = request("datecreated")
Dim objConn, objCmd, objRs
Set objConn = Server.CreateObject("ADODB.Connection")
Set objCmd = Server.CreateObject("ADODB.Command")
Set objRs = Server.CreateObject("ADODB.RecordSet")
objConn.CursorLocation = adUseClient '游标位置设置为客户端,必须
Dim strConnection
'Use the correct SQL*NET connect string!
strConnection="PROVIDER=OraOLEDB.Oracle;DATA SOURCE=test;USER ID=test;PASSWORD=test;PLSQLRSet=1"
objConn.Open strConnection
objCmd.ActiveConnection = objConn
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "curspkg_join.p_test"
objCmd.Parameters.Append objCmd.CreateParameter("param1", adVarChar, adParamInput, 20, datecreated)
Set objRs = objCmd.Execute
%>
<table width="100%" border="0" cellspacing="1" cellpadding="2" bgcolor="#000000">
<tr bgcolor="#dcdcdc" align="center">
<td width="30%">column_1</td>
<td width="30%">column_2</td>
<td>column_3</td>
</tr>
<%
response.write objRs.recordcount
do while not objRs.EOF
%>
<tr bgcolor="#FFFFFF" align="center">
<td><%=objRs(0)%></td>
<td><%=objRs(1)%></td>
<td><%=objRs(2)%></td>
</tr>
<%
objRs.movenext
loop
%>
</table>
<%
objRs.Close
Set objRs = Nothing
Set objCmd = Nothing
objConn.Close
Set objConn = Nothing
%>
</body>
</html>
java 也有类似的方法:
......
prepStmt = conn.prepareStatement(sqlstr,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
// 执行
ResultSet rs = prepStmt.executeQuery();
rs.setFetchSize(1000);
rs.setFetchDirection(ResultSet.FETCH_UNKNOWN);
rs.last();
rs.getRow();
......
但无论哪种方法,应该也是用循环计数器的方法实现的,特别是 java,要是不用 rs.setFetchSize 对大的结果集 rs.last()会很慢。所以本质上和自己用 loop fetch 得到记录数应该差不多。不知道对否,高手的看法呢?
在网上搜了一下,单从 Oracle 数据库没有什么好办法。oracle并不是一次提取出全部的结果集的,因此要获得一个结果集的总数,只能做两次,一次打开cursor or ref cursor;第二次来个循环fetch。如果是查询一个表的总数,只能使用count函数才能获得总数,而不是%rowcount。
但是通过外部调用程序的属性或方法应该可以做到。如asp 里用 rs.recodecount,源代码如下:
<!-- #include file="adovbs.inc" -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>test</title>
<link href="../css/font.css" rel="stylesheet" type="text/css">
</head>
<body>
<%
datecreated = request("datecreated")
Dim objConn, objCmd, objRs
Set objConn = Server.CreateObject("ADODB.Connection")
Set objCmd = Server.CreateObject("ADODB.Command")
Set objRs = Server.CreateObject("ADODB.RecordSet")
objConn.CursorLocation = adUseClient '游标位置设置为客户端,必须
Dim strConnection
'Use the correct SQL*NET connect string!
strConnection="PROVIDER=OraOLEDB.Oracle;DATA SOURCE=test;USER ID=test;PASSWORD=test;PLSQLRSet=1"
objConn.Open strConnection
objCmd.ActiveConnection = objConn
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "curspkg_join.p_test"
objCmd.Parameters.Append objCmd.CreateParameter("param1", adVarChar, adParamInput, 20, datecreated)
Set objRs = objCmd.Execute
%>
<table width="100%" border="0" cellspacing="1" cellpadding="2" bgcolor="#000000">
<tr bgcolor="#dcdcdc" align="center">
<td width="30%">column_1</td>
<td width="30%">column_2</td>
<td>column_3</td>
</tr>
<%
response.write objRs.recordcount
do while not objRs.EOF
%>
<tr bgcolor="#FFFFFF" align="center">
<td><%=objRs(0)%></td>
<td><%=objRs(1)%></td>
<td><%=objRs(2)%></td>
</tr>
<%
objRs.movenext
loop
%>
</table>
<%
objRs.Close
Set objRs = Nothing
Set objCmd = Nothing
objConn.Close
Set objConn = Nothing
%>
</body>
</html>
java 也有类似的方法:
......
prepStmt = conn.prepareStatement(sqlstr,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
// 执行
ResultSet rs = prepStmt.executeQuery();
rs.setFetchSize(1000);
rs.setFetchDirection(ResultSet.FETCH_UNKNOWN);
rs.last();
rs.getRow();
......
但无论哪种方法,应该也是用循环计数器的方法实现的,特别是 java,要是不用 rs.setFetchSize 对大的结果集 rs.last()会很慢。所以本质上和自己用 loop fetch 得到记录数应该差不多。不知道对否,高手的看法呢?