指针 (数据库)
数据指针(Data Cursor)或称光标,是在数据库引擎 (Database Engine)中,让开发人员或数据库管理员可以遍历、浏览检索结果的数据行(称为数据查询结果集, Result set),是主要用于在结果集中移动到某一数据行(row)的控制结构。光标可以被看作是指向一组行中,代表某一行的指针。光标一次只能引用一行,但可以根据需要移动到结果集的其他行。
光标有助于随检索之后的数据处理与遍历相结合,如添加和删除记录。它能遍历数据查询结果集的特性,类似于编程语言的迭代器概念。开发程序人员通常依需求而使用光标,来处理由数据库系统查询返回的整个结果集。在这种情况下,光标可使结果集中的数据行依照次序处理。在SQL程序中,使用光标可以定义检索集(多行数据行的条件选取组合)并逐行执行数据处理的逻辑。通过相同的机制,SQL程序也可将结果集直接返回给调用者或客户端应用程式;也常会被外部的数据存取接口所使用,像是 ADO、JDBC、 ADO.NET、PL-SQL 等都有数据指针的应用。
原理
编辑数据指针是在数据库产生结果集时,由数据库引擎所产生的一个指针,用来指示目前正在存取的结果集的位置,经由这个指针,可以得到结果集中的数据行,并且可以依照需求来移动,但由于指针会占用伺服器的资源,并且在指针开启期间会激活共享锁定(Shared Lock),在多人使用的系统中容易造成死锁的问题,因此目前大部分的应用程式都是使用仅前移型指针 (Forward-Only Cursor)。
种类
编辑依照功能来区分,有四种[1]。
静态指针
编辑静态指针 (Static Cursor) 是利用暂存数据表作为存储结果集空间的一种指针,它可以让应用程式可以快速的存取结果集,但在静态指针开启期间,任何对数据表所做的变更都不会反映在结果集中;同时,在静态指针中所作的修改,无法反映到数据库中,此种指针是消耗资源度第三的指针。
动态指针
编辑动态指针 (Dynamic Cursor) 是可以反映数据库中修改的一种指针,不过它并不会让结果集的位置固定 (随机变动),因此无法确实的以指针位置来判断数据,并且它因为要随时反映数据库的变化,因此伺服器需要消耗较多的资源,此种指针是消耗资源第二高的指针。
索引键集型指针
编辑索引键集指针 (Keyset Cursor) 是动态指针的强化版本,借由维护一个数据集位置对应表 (以 SQL Server 为例,会建立在 tempdb 的 keyset 数据表中),以维护在结果集中的顺序不受更新而变化,但这相对的也付出了伺服器性能和资源消耗的代价,因此索引键集指针是最消耗伺服器资源的一种指针,在实务上应避免使用。
仅前移型指针
编辑仅前移型指针 (Forward-Only Cursor) 是一旦将指针往前移时,其走过的指针之前的结果集就会被舍弃,因此应用程式不能再往后移动指针,但也因此让伺服器只需要记住指针在结果集中目前的位置即可,这让它消耗的资源只有指针而已,是最省资源的一种指针,在实务中被广泛使用,像 ADO.NET 的 DataReader 就只限定只能使用 Forward-Only Cursor。
可滚动或不可滚动
编辑数据库指针又分为可滚动性 (scrollable cursor) 指针与不可滚动性指针,可滚动性指针代表数据库指针可以依据指针的操作指令来移动,像是向前 (NEXT)、向后 (BACK)、朝指定位置移动等等性质。此种指针在执行数据库复制 (Replication) 时,是一个相当重要的能力,但可滚动性指针又会比不可滚动性指针消耗更多的资源。
缺点
编辑数据库指针有三个缺点:
- 若在网络应用程式中使用,会造成大量的网络来回(Round-trip),让网络流量大增。
- 若在多人应用程式中大量使用指针,会造成大量的锁定,因此使用不当的话,让数据库发生死锁的几率会大增。
- 在SQL存储程序或SQL预存函数使用时,如果在巢式循环之中使用多个数据库指针,将使得数据的存取性能严重低落。