
你逻辑流程有问题 ,下面是你的逻辑流程,
读取下一条→加值→[判断是否结尾→读取下一条→加值](循环)
而@@FETCH_STATUS返回3种状态,
0 FETCH 语句成功。
-1 FETCH 语句失败或此行不在结果集中。
-2 被提取的行不存在。
这样在游标移动到最后一行的时候,进行while判断@@FETCH_STATUS为0 ,进行一次加值,然后又直接进入while判断 这时候你还没有移动游标,@@FETCH_STATUS还是为0,又进行了一次加值,然后移动游标,进行判断@@FETCH_STATUS不为0,退出循环
所以应该修改逻辑为
读取下一条→[判断是否结尾→加值→读取下一条](循环)
SQL语句调整如下
===========================================
OPEN Employee_Cursor
FETCH NEXT FROM Employee_Cursor into @id,@name
WHILE @@FETCH_STATUS = 0
BEGIN
set @finalname = @finalname + @name
FETCH NEXT FROM Employee_Cursor into @id,@name
END
CLOSE Employee_Cursor
==================================
以上语句实测试通过
先移动游标,然后就开始判断,为真进行加值 然后移动游标,这样就没问题了,
游标是SQL的一个内存工作区 由系统或用户以变量的形式定义 游标的作用就是用于临时存储从数据库中提取的数据块
Oracle数据库的Cursor类型包含三种 静态游标 分为显式(explicit)游标和隐式(implicit)游标 REF游标 是一种引用类型 类似于指针
测试数据
create table student(sno number primary key sname varchar ( ))
declare i number:= ;
beginwhile i<=
loop
insert into student(sno sname) values (i name ||to_char(i))
i:=i+ ;
end loop;
end;
隐式游标属性
SQL%ROWCOUNT 整型代表DML语句成功执行的数据行数
SQL%FOUND 布尔型值为TRUE代表插入 删除 更新或单行查询 *** 作成功
SQL%NOTFOUND 布尔型与SQL%FOUND属性返回值相反
SQL%ISOPEN 布尔型DML执行过程中为真 结束后为假
declarebegin update student set sname = name ||to_char(sno ) where sname= name ;
if sql%found then
dbms_output put_line( name is updated )
else
dbms_output put_line( 没有记录 )
end if;
end;
declare
begin
for names in (select from student) loop
dbms_output put_line(names sname)
end loop;
exception when others then
dbms_output put_line(sqlerrm)
end;
显式游标属性
%ROWCOUNT 获得FETCH语句返回的数据行数
%FOUND 最近的FETCH语句返回一行数据则为真 否则为假
%NOTFOUND 布尔型 与%FOUND属性返回值相反
%ISOPEN 布尔型 游标已经打开时值为真 否则为假
对于显式游标的运用分为四个步骤
a 定义游标 Cursor [Cursor Name] IS;
b 打开游标 Open [Cursor Name];
c *** 作数据 Fetch [Cursor name];
d 关闭游标 Close [Cursor Name];
典型显式游标
declare cursor cur_rs is select from student; sinfo student%rowtype;
begin open cur_rs;
loop
fetch cur_rs into sinfo;
exit when cur_rs%%notfound;
dbms_output put_line(sinfo sname)
end loop;
exception when others then
dbms_output put_line(sqlerrm)
end;
带参数open的显式cursor:
declare cursor cur_rs(in_name varchar ) is select
from student where sname=in_name;
begin for sinfo in cur_rs( sname ) loop
dbms_output put_line(sinfo sname)
end loop;
exception when others then
dbms_output put_line(sqlerrm)
end;
使用current of语句执行update或delete *** 作
declare
cursor cur_rs is select from student for update;
begin for sinfo in cur_rs loop
update student set sname=sname|| xx where current of cur_rs;
end loop;
mit;
exception when others then
dbms_output put_line(sqlerrm)
end;
REF游标 用于处理运行时才能确定的动态sql查询结果 利用REF CURSOR 可以在程序间传递结果集(一个程序里打开游标变量 在另外的程序里处理数据)
也可以利用REF CURSOR实现BULK SQL 提高SQL性能
REF CURSOR分两种 Strong REF CURSOR 和 Weak REF CURSOR
Strong REF CURSOR: 指定retrun type CURSOR变量的类型必须和return type一致
Weak REF CURSOR: 不指定return type 能和任何类型的CURSOR变量匹配
运行时根据动态sql查询结果遍历
create or replace package pkg_test as
type student_refcursor_type is ref cursor return student%rowtype;
procedure student_rs_loop(cur_rs IN student_refcursor_type)
end pkg_test ;
create or replace package body pkg_test as
procedure student_rs_loop(cur_rs IN student_refcursor_type) is
std student%rowtype;
begin loop
fetch cur_rs into std;
exit when cur_rs%NOTFOUND;
dbms_output put_line(std sname)
end loop;
end student_rs_loop;
end pkg_test ;
declare stdRefCur pkg_test student_refcursor_type;
begin for i in loop
dbms_output put_line( Student NO= || i)
open stdRefCur for select from student where sno=i;
pkg_test student_rs_loop(stdRefCur)
end loop;
exception when others then dbms_output put_line(sqlerrm)
close stdRefCur;
end;
使用FORALL和BULK COLLECT子句 利用BULK SQL可以减少PLSQL Engine和SQL Engine之间的通信开销 提高性能
加速INSERT UPDATE DELETE语句的执行 也就是用FORALL语句来替代循环语句
加速SELECT 用BULK COLLECT INTO 来替代INTO
create table
student_tmp as select sno
sname from student where = ;
删除主键约束 alter table student drop constraint SYS_C ;
执行两遍插入 insert into student select from student where sno= ;
declare cursor cur_std(stdid student sno%type) is select sno
sname from student where sno=stdid;
type student_table_type is table of cur_std%rowtype index by pls_integer;
student_table student_table_type;
begin
open cur_std( )
fetch cur_std bulk collect into student_table;
close cur_std;
for i in unt loop
dbms_output put_line(student_table(i) sno ||
|| student_table(i) sname)
end loop;
forall i in student_table firststudent_table last
insert into student_tmp values(student_table(i) sno student_table(i) sname)
mit;
end;
lishixinzhi/Article/program/Oracle/201311/17358
一个好的数据库产品不等于就有一个好的应用系统 如果不能设计一个合理的数据库模型 不仅会增加客户端和服务器段程序的编程和维护的难度 而且将会影响系统实际运行的性能 一般来讲 在一个MIS系统分析 设计 测试和试运行阶段 因为数据量较小 设计人员和测试人员往往只注意到功能的实现 而很难注意到性能的薄弱之处 等到系统投入实际运行一段时间后 才发现系统的性能在降低 这时再来考虑提高系统性能则要花费更多的人力物力 而整个系统也不可避免的形成了一个打补丁工程 笔者依据多年来设计和使用数据库的经验 提出以下一些设计准则 供同仁们参考
命名的规范
不同的数据库产品对对象的命名有不同的要求 因此 数据库中的各种对象的命名 后台程序的代码编写应采用大小写敏感的形式 各种对象命名长度不要超过 个字符 这样便于应用系统适应不同的数据库
游标(Cursor)的慎用
游标提供了对特定集合中逐行扫描的手段 一般使用游标逐行遍历数据 根据取出的数据不同条件进行不同的 *** 作 尤其对多表和大表定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等特甚至死机 笔者在某市《住房公积金管理系统》进行日终帐户滚积数计息处理时 对一个 万个帐户的游标处理导致程序进入了一个无限期的等特(后经测算需 个小时才能完成)(硬件环境 Alpha/ Mram Sco Unix Sybase ) 后根据不同的条件改成用不同的UPDATE语句得以在二十分钟之内完成 示例如下
Declare Mycursor cursor for select count_no from COUNT
Open Mycursor
Fetch Mycursor into @vcount_no
While (@@sqlstatus= )
Begin
If @vcount_no= 条件
*** 作
If @vcount_no= 条件
*** 作
Fetch Mycursor into @vcount_no
End
改为
Update COUNT set *** 作 for 条件
Update COUNT set *** 作 for 条件
在有些场合 有时也非得使用游标 此时也可考虑将符合条件的数据行转入临时表中 再对临时表定义游标进行 *** 作 可时性能得到明显提高 笔者在某地市〈电信收费系统〉数据库后台程序设计中 对一个表( 万行中符合条件的 多行数据)进行游标 *** 作(硬件环境 PC服务器 PII Mram NT Ms Sqlserver ) 示例如下
Create #tmp / 定义临时表 /
(字段
字段
)
Insert into #tmp select from TOTAL where
条件 / TOTAL中 万行 符合条件只有几十行 /
Declare Mycursor cursor for select from #tmp
/对临时表定义游标/
索引(Index)的使用原则
创建索引一般有以下两个目的 维护被索引列的唯一性和提供快速访问表中数据的策略 大型数据库有两种索引即簇索引和非簇索引 一个没有簇索引的表是按堆结构存储数据 所有的数据均添加在表的尾部 而建立了簇索引的表 其数据在物理上会按照簇索引键的顺序存储 一个表只允许有一个簇索引 因此 根据B树结构 可以理解添加任何一种索引均能提高按索引列查询的速度 但会降低插入 更新 删除 *** 作的性能 尤其是当填充因子(Fill Factor)较大时 所以对索引较多的表进行频繁的插入 更新 删除 *** 作 建表和索引时因设置较小的填充因子 以便在各数据页中留下较多的自由空间 减少页分割及重新组织的工作
数据的一致性和完整性
为了保证数据库的一致性和完整性 设计人员往往会设计过多的表间关联(Relation) 尽可能的降低数据的冗余 表间关联是一种强制性措施 建立后 对父表(Parent Table)和子表(Child Table)的插入 更新 删除 *** 作均要占用系统的开销 另外 最好不要用Identify 属性字段作为主键与子表关联 如果数据冗余低 数据的完整性容易得到保证 但增加了表间连接查询的 *** 作 为了提高系统的响应时间 合理的数据冗余也是必要的 使用规则(Rule)和约束(Check)来防止系统 *** 作人员误输入造成数据的错误是设计人员的另一种常用手段 但是 不必要的规则和约束也会占用系统的不必要开销 需要注意的是 约束对数据的有效性验证要比规则快 所有这些 设计人员在设计阶段应根据系统 *** 作的类型 频度加以均衡考虑
事务的陷阱
事务是在一次性完成的一组 *** 作 虽然这些 *** 作是单个的 *** 作 SQL Server能够保证这组 *** 作要么全部都完成 要么一点都不做 正是大型数据库的这一特性 使得数据的完整性得到了极大的保证
众所周知 SQL Server为每个独立的SQL语句都提供了隐含的事务控制 使得每个DML的数据 *** 作得以完整提交或回滚 但是SQL Server还提供了显式事务控制语句
BEGIN TRANSACTION 开始一个事务
MIT TRANSACTION 提交一个事务
ROLLBACK TRANSACTION 回滚一个事务
事务可以嵌套 可以通过全局变量@@trancount检索到连接的事务处理嵌套层次 需要加以特别注意并且极容易使编程人员犯错误的是 每个显示或隐含的事物开始都使得该变量加 每个事务的提交使该变量减 每个事务的回滚都会使得该变量置 而只有当该变量为 时的事务提交(最后一个提交语句时) 这时才把物理数据写入磁盘
数据库性能调整
在计算机硬件配置和网络设计确定的情况下 影响到应用系统性能的因素不外乎为数据库性能和客户端程序设计 而大多数数据库设计员采用两步法进行数据库设计 首先进行逻辑设计 而后进行物理设计 数据库逻辑设计去除了所有冗余数据 提高了数据吞吐速度 保证了数据的完整性 清楚地表达数据元素之间的关系 而对于多表之间的关联查询(尤其是大数据表)时 其性能将会降低 同时也提高了客 户端程序的编程难度 因此 物理设计需折衷考虑 根据业务规则 确定对关联表的数据量大小 数据项的访问频度 对此类数据表频繁的关联查询应适当提高数据冗余设计
数据类型的选择
数据类型的合理选择对于数据库的性能和 *** 作具有很大的影响 有关这方面的书籍也有不少的阐述 这里主要介绍几点经验
Identify字段不要作为表的主键与其它表关联 这将会影响到该表的数据迁移
Text 和Image字段属指针型数据 主要用来存放二进制大型对象(BLOB) 这类数据的 *** 作相比其它数据类型较慢 因此要避开使用
日期型字段的优点是有众多的日期函数支持 因此 在日期的大小比较 加减 *** 作上非常简单 但是 在按照日期作为条件的查询 *** 作也要用函数 相比其它数据类型速度上就慢许多 因为用函数作为查询的条件时 服务器无法用先进的性能策略来优化查询而只能进行表扫描遍历每行
例如 要从DATA_TAB 中(其中有一个名为DATE的日期字段)查询 年的所有记录
lishixinzhi/Article/program/Oracle/201311/17929
--建立消游标
declare xs_cur cursor
for
select from xsb
where 性别='女'
for read only
go
--打开游标
open xs_cur
--使用游标
fetch next from xs_cur
while @@fetch_status=0
begin
fetch next from xs_cur
end
--关闭游标
close xs_cur
--删除游标
deallocate xs_cur
以上就是关于100分 求教SQLSERVER中的用游标遍历表中的列并实现累加输出。全部的内容,包括:100分 求教SQLSERVER中的用游标遍历表中的列并实现累加输出。、Oracle数据库游标的类型、大型数据库设计原则等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)