关系数据库中的操作会对整个行集产生影响。由SELECT语句返回的行集包括所有满足该语句WHERE子句中条件的行,由语句所返回的完整的行集被称为结果集。应用程序,特别是交互式联机应用程序,并不总能将整个结果集作为一个单元来有效地处理,这些应用程序需要一种机制以便每次处理一行或一部分行,游标就是提供这种机制的结果集扩展。
游标通过以下方式扩展结果处理:
- 允许定位在结果集的特定行。
- 从结果集的当前位置检索一行或多行。
- 支持对结果集中当前位置的行进行数据修改。
- 为由其他用户对显示在结果集中的数据库数据所做的更改提供不同级别的可见性支持。
- 提供脚本、存储过程和触发器中使用的访问结果集中的数据的Transact-SQL语句。
建立游标的语法如下:
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] ] |
建立游标语法中各参数的说明如表所示。
表 建立游标语法中的参数列表
参数 | 说明 |
cursor_name | 所定义的Transact-SQL服务器游标名称 |
LOCAL | 指定该游标的作用域对在其中创建它的批处理、存储过程或触发器是局部的。该游标名称仅在这个作用域内有效。在批处理、存储过程、触发器或存储过程OUTPUT参数中,该游标可由局部游标变量引用。OUTPUT参数用于将局部游标传递回调用批处理、存储过程或触发器,它们可在存储过程终止后给游标变量指派参数使其引用游标。除非OUTPUT参数将游标传递回来,否则游标将在批处理、存储过程或触发器终止时隐性释放。如果OUTPUT参数将游标传递回来,游标在最后引用它的变量释放或离开作用域时释放 |
GLOBAL | 指定该游标的作用域对连接是全局的。在由连接执行的任何存储过程或批处理中,都可以引用该游标名称。该游标仅在脱接时隐性释放 |
FORWARD_ONLY | 指定游标只能从第一行滚动到最后一行。FETCH NEXT是唯一受支持的提取选项。如果在指定FORWARD_ONLY时不指定STATIC、KEYSET和DYNAMIC关键字,则游标作为DYNAMIC游标进行操作。如果FORWARD_ONLY和SCROLL均未指定,除非指定STATIC、KEYSET或DYNAMIC关键字,否则默认为FORWARD_ONLY。STATIC、KEYSET和DYNAMIC游标默认为SCROLL。与ODBC和ADO这类数据库API不同,STATIC、KEYSET 和DYNAMIC Transact-SQL游标支持FORWARD_ONLY |
STATIC | 定义一个游标,以创建将由该游标使用的数据的临时复本。对游标的所有请求都从tempdb中的该临时表中得到应答;因此,在对该游标进行提取操作时返回的数据中不反映对基表所做的修改,并且该游标不允许修改 |
KEYSET | 指定当游标打开时,游标中行的成员资格和顺序已经固定。对行进行唯一标识的键集内置在tempdb内一个称为keyset的表中。对基表中的非键值所做的更改(由游标所有者更改或由其他用户提交)在用户滚动游标时是可视的。其他用户进行的插入是不可视的(不能通过Transact-SQL服务器游标进行插入)。如果某行已删除,则对该行的提取操作将返回@@FETCH_STATUS值-2。从游标外更新键值类似于删除旧行后接着插入新行的操作。含有新值的行不可视,对含有旧值的行的提取操作将返回@@FETCH_STATUS值-2。如果通过指定WHERE CURRENT OF子句用游标完成更新,则新值可视 |
DYNAMIC | 定义一个游标,以反映在滚动游标时对结果集内的行所做的所有数据更改。行的数据值、顺序和成员在每次提取时都会更改。动态游标不支持 ABSOLUTE提取选项 |
FAST_FORWARD | 指定启用了性能优化的FORWARD_ONLY、READ_ONLY游标 |
READ_ONLY | 禁止通过该游标进行更新。在UPDATE或DELETE语句的WHERE CURRENT OF子句中不能引用游标。该选项替代要更新的游标的默认功能 |
SCROLL_LOCKS | 指定确保通过游标完成的定位更新或定位删除可以成功。当将行读入游标以确保它们可用于以后的修改时,Microsoft® SQL Server™会锁定这些行。如果还指定了FAST_FORWARD,则不能指定SCROLL_LOCKS |
OPTIMISTIC | 指定如果行自从被读入游标以来已得到更新,则通过游标进行的定位更新或定位删除不成功。当将行读入游标时SQL Server不锁定行。相反,SQL Server使用timestamp列值的比较,或者如果表没有timestamp列则使用校验值,以确定将行读入游标后是否已修改该行 |
TYPE_WARNING | 指定如果游标从所请求的类型隐性转换为另一种类型,则给客户端发送警告消息 |
示例 建立游标
建立游标,通过游标来完成特定信息的提取功能,如果People_cursor数据表中存在10条记录,通过游标可以提取指定一条员工信息。
程序代码如下:
create proc Proc_cursorNum @Num int as begin DECLARE People_cursor SCROLL CURSOR FOR SELECT * FROM t_People ORDER BY tb_PID open People_cursor FETCH ABSOLUTE @Num FROM People_cursor deallocate People_cursor end |
当程序运行的时候,调用存储过程,并通过存储过程操作游标来完成特定信息的提取(如获取工编号为P1006的员工信息)。
程序代码如下:
Num_ProcOfCussor方法用于调用存储过程“Proc_cursorNum”同时传入所需的信息编号,将返回结果放入结果集中。
public DataSet Num_ProcOfCussor(int Num) { try { SqlDataAdapter da = new SqlDataAdapter("Proc_cursorNum", ConDB()); da.SelectCommand.CommandType = CommandType.StoredProcedure; da.SelectCommand.Parameters.Add("@Num", SqlDbType.Int).Value = Num; DataSet ds = new DataSet(); da.Fill(ds); return ds; } catch { return null; } } |
单击【查找】按钮,将行号传给Num_ProcOfCussor方法,并获得指定行的数据信息。【查找】按钮的Click事件代码如下:
private void button3_Click(object sender, EventArgs e) { ClsDB.ClsCussor CU = new OptDB.ClsDB.ClsCussor(); int Num; try { Num = int.Parse(this.textBox1.Text.Trim().ToString()); } catch (Exception ey) { MessageBox.Show(ey.Message); return; } this.dataGridView1.DataSource = CU.Num_ProcOfCussor(Num).Tables[0].DefaultView; } |