晕,my god
再看源码就受不了啦反正大致明白你的意思了吧?这东西数据库自己就能完成了select user.*,usertype.* from user, usertype where user.UserTypeId = usertype.UsertypeId或者用inner join .等等
再或者到数据库里建视图
不用自己写
晕了晕了,上面那个语句读一次数据库出来的东西应该就是你想要的
再看源码就受不了啦反正大致明白你的意思了吧?这东西数据库自己就能完成了select user.*,usertype.* from user, usertype where user.UserTypeId = usertype.UsertypeId或者用inner join .等等
再或者到数据库里建视图
不用自己写
晕了晕了,上面那个语句读一次数据库出来的东西应该就是你想要的
1.以上例子是用来分析数据库访问技术的,所以虽然该例能够用复杂的sql语句来实现,但是我们不用。
因为在循环内嵌套的可以不仅仅是一个select语句,而且可以是insert、update等语句,或者是一个方法,而这个方法中又包含了select语句、insert、update等语句。
比如银行的代理业务:
外面的循环是对个人收付表的读取,
里面则是一个扣款的方法,而这个方法,又涉及到修改账户表,在分户明细表中增加一笔明细,帐务流水表中增加一笔流水,会计分录表中增加若干笔会计分录。
在使用 OleDbDataReader 时,相关联的 OleDbConnection 忙于为 OleDbDataReader 服务,
对 OleDbConnection 不能执行任何其他操作,只能关闭 。
这种情况会一直持续到调用 OleDbDataReader 的 Close 方法为止。(载自msdn)
文中提到的四种方式是两种方式的组合。
在informix-esql中,select游标对应于ADO.NET的DataReader。
informix好像也不允许游标的嵌套(记不清楚了)。
但是,从informix的表中读取一条记录,不需要使用游标,可以直接读取到宿主变量中,这样就不至于造成游标嵌套。
举例如下:
SELECT * INTO $stUsertype FROM usertype WHERE UserTypeId = $iUserTypeId stUsertype是一个结构体。
你说的放在数据库中完成,是否指的是采用存储程序
这里没有采用存储程序,主要考虑的是数据库的移植问题,比如移植到access版本,他没有存储程序,怎么移植啊。
另外,存储程序一般用来提供短小、常用的函数,大部分的业务处理还是用代码方式来处理的,比如前面提到的代理程序,实际做起来要上千行,是不会考虑采用存储程序的。
另外,你说的非要不停的向服务器送出语句然后取数据,这个服务器指的是数据库还是应用服务器?以上四种方式,都是运行在应用服务器上的。
呵呵.:)
你所有的例子考虑的都是循环
举例说 User 表 有 10000条记录
在取userType的时候 这个循环就执行了 10000 次 向数据库 "select UserType"的 SQL
不用复杂的SQL语句
很好的解决方案也是这样的
UserType表不应该会有很多条记录. 不可能会 每个用户单独是一种类型吧?
所以DataAdapter 和 DataSet这时候就有用了
流程是这样:
建Connection
将UserType 写入DataSet
(Fill完之后Connection就可以用于其他操作)
DataReader ( Select * from [user])
while (.Read())
{
//操作DataSet. 从中Select 出此ID的类型名
//这才是DataSet的优势吧? 而不是在 一个大循环里还要不停的将相同数据Fill进DataSet
//它们都已经在内存中,
//可脱机操作的DataSet与 一次一行只读前进的Reader
//很明显的不同应用
}
释放资源
以上就是为什么用DataSet的例子.因为它的特性决定了,根本不用循环10000次去Fill它那么再说说为什么要用复杂语句查询
select [user].UserName,usertype.UserTypeName from [user], usertype where [user].UserTypeId = usertype.UsertypeId
这个SQL语句就是语句, 并不是存储过程.这个要分清楚了
我可以保证当今使用的数据库,90%以上都可以执行(就不说100%了.呵呵 *_*)
流程如下:
建Connection
DataReader Reader = Command.ExecuteReader() // 上面的语句
while (Reader.Read())
{
strResult += Reader["UserName"] + Reader["UserTypeName"] + "\n";
}
Reader.Close();
释放Connection
简单的完成任务
你只要告诉数据库你想要什么样的数据,它给你提供这些数据
为什么数据要这样关联.那是在数据服务器完成的
呼...不知道你了解我想说什么没有.
有什么不同意见再来讨论
谢谢你参与探讨。
我想,可能是我提供的背景或者例子描述得不够清楚,让你产生了误解。我重新说说:
我的目的是用来分析数据库访问技术的,特别是在极限情况下一些研究。
我重新举一个 银行代收水费的例子,你可以考虑一下如何实现:
表:个人收付表:
字段名称 类型 备注
---------------------------
no int 编号
name string 姓名
account string 账号
money double 金额
ProcFlag string 处理标志
分户表:
字段名称 类型 备注
-------------------------------
account string 账号
AccountName string 户名
SaveMoney double 存款余额 说明:一般一次待收水费的户数,可以达到10万户,而分户表,随随便便都是上100万条记录的。代收水费的流程:
while ( 读取一个水费户 )
{
1.从分户表中取出对应帐户的记录,不存在,则修改个人收付表当前记录的处理标志,continue
2.判断户名是否符合,余额是否足够等等
3.修改分户表的存款余额
4.修改个人收付表的处理标志
}
我目前考虑到处理方式是将水费户读取到一个datatable中,那么datatable就有10万条记录。
while内部读取分户表的一条记录用DataReader或DataSet都可以。
分户表的记录 > 个人收付表。你说的是这种情况吧?
并且 个人收付表中的账户可能在 分户表中不存在?不过即然有处理标志的话如果让我写代码是这样select from 表1,表2 where 表1.account = 表2.accountwhile
{
处理
}
select from 表1 where 标志 = 未处理
while
{
使用你写的方法之一
// 其实这里就应该只是在 表1 中所写帐号.在表2中没有的情况
}我想会比直接循环处理效率高一些吧
要建两个Connection
是三个
还有一个要为Command的Update使用
启动事务有两种情况,一种在循环外启动,是一个大事务,一个是在内启动,一户一个事务。
代收水费采用一户一个事务的方式。
我以前也建立两个连接,涉及到事务时出现过问题,刚才重新试了一下,又可以了。
我现在的策略如下:小表的循环采用dataset(因为不用再建立连接),大表的循环采用DataReader,建立两个连接。
谢谢你的参与,让我搞定这个问题,等你回贴后我就给分结贴。
附录:流程
1.大事务
打开连接1,用于读取水费户
打开连接2,用户处理一户水费
启动连接2.事务
while
{
打开连接2.DataReader
处理...
关闭连接2.DataReader
}
关闭事务
关闭连接2
关闭连接2.小事务
打开连接1,用于读取水费户
while
{
打开连接2,用户处理一户水费
启动连接2.事务
打开连接2.DataReader
处理...
关闭连接2.DataReader
关闭事务
关闭连接2
}
关闭连接