第四十三章 SQL命令 FETCH

第四十三章 SQL命令 FETCH

重新定位游标,并从中检索数据。

大纲

FETCH cursor-name [INTO host-variable-list ]

参数

  • cursor-name - 当前打开的游标的名称。
    游标名称是在DECLARE命令中指定的。
    游标名称区分大小写。
  • INTO host-variable-list - 可选—将取操作列中的数据放入局部变量中。
    host-variable-list指定一个主机变量或一个逗号分隔的主机变量列表,它们是包含与游标关联的数据的目标。
    INTO句是可选的。
    如果没有指定,FETCH语句只定位游标。

描述

在嵌入式SQL应用程序中,FETCH语句从游标检索数据。
所需的操作顺序是:DECLAREOPENFETCHCLOSE
在未打开的游标上尝试FETCH会导致SQLCODE -102错误。

作为SQL语句,这只在嵌入式SQL中得到支持。
通过ODBC使用ODBC API支持等价的操作。

INTO子句可以指定为DECLARE语句的子句,也可以指定为FETCH语句的子句,或者两者都指定。
INTO子句允许将fetch列中的数据放到本地主机变量中。
列表中的每个主机变量,从左到右,都与游标结果集中的相应列相关联。
每个变量的数据类型必须匹配或支持对应结果集列的数据类型的隐式转换。
变量的数量必须与游标选择列表中的列数匹配。

当游标前进到数据的末尾时,FETCH操作就完成了。
这将设置SQLCODE=100(没有更多数据)。
它还将%ROWCOUNT变量设置为获取的行数。

注意:只有当SQLCODE=0时,INTO子句宿主变量返回的值才是可靠的。
如果SQLCODE=100(没有更多数据),则不应该使用主机变量值。

游标名称不是特定于名称空间的。
更改当前名称空间对声明游标的使用没有影响。
唯一需要考虑的名称空间是FETCH必须出现在包含要查询的表的名称空间中。

%ROWID

FETCH检索可更新游标的行时,它将%ROWID设置为所获取行的ROWID值。
可更新游标是指顶部FROM子句只包含一个元素(表名或可更新视图名)的游标。

为检索到的每一行设置%ROWID受以下条件的限制:

  • DECLARE cursorname CURSOROPEN cursorname语句不初始化%ROWID;
    %ROWID值与之前的值不变。
    第一个成功的FETCH设置%ROWID
    每个后续的FETCH检索行都会将%ROWID重置为当前的ROWID
    FETCH如果检索可更新游标的行,则设置%ROWID
    如果游标不可更新,%ROWID将保持不变。
    如果没有匹配查询选择条件的行,FETCH不会更改之前的%ROWID值。
    CLOSEFETCH发出SQLCODE 100 (No Data, or No More Data)时,%ROWID包含检索到的最后一行的ROWID
  • 带有DISTINCT关键字或GROUP BY子句的基于游标的SELECT不会设置%ROWID
    %ROWID值与之前的值(如果有的话)保持不变。
  • 基于游标的SELECT只执行聚合操作,不设置%ROWID
    %ROWID值与之前的值(如果有的话)保持不变。

没有声明游标的嵌入式SQL SELECT不会设置%ROWID
在完成一个简单的SELECT语句后,%ROWID值是不变的。

FETCH for UPDATE or DELETE

可以使用FETCH来检索要进行更新或删除的行。
UPDATEDELETE必须指定WHERE CURRENT OF子句。
DECLARE应该指定FOR UPDATE子句。
下面的示例显示了一个基于游标的删除操作,它删除所有选中的行:

ClassMethod FETCH()
{
    s $NAMESPACE="Samples"
    &sql(
        DECLARE MyCursor CURSOR FOR SELECT %ID,Status
        FROM Sample.Quality WHERE Status='Bad' FOR UPDATE
    )
    &sql(
        OPEN MyCursor
    )
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    n %ROWCOUNT,%ROWID
    for {
        &sql(
            FETCH MyCursor
        )  
        q:SQLCODE'=0
        &sql(
            DELETE FROM Sample.Quality WHERE CURRENT OF MyCursor
        ) 
    }
    w !,"更新的行数=",%ROWCOUNT
    &sql(
        CLOSE MyCursor
    )
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}

示例

下面的嵌入式SQL示例显示了一个无参数的FOR循环调用FETCH,从名为EmpCursor的游标检索数据。
INTO子句在DECLARE语句中指定:

ClassMethod FETCH1()
{
    &sql(
        DECLARE EmpCursor CURSOR FOR 
            SELECT Name, Home_State
            INTO :name,:state FROM Sample.Employee
            WHERE Home_State %STARTSWITH 'M'
    )
    &sql(
        OPEN EmpCursor
    )
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    n %ROWCOUNT,%ROWID
    for { 
        &sql(
            FETCH EmpCursor
        )
        q:SQLCODE'=0  
        w "count: ",%ROWCOUNT," RowID: ",%ROWID,!
        w "  Name=",name," State=",state,! 
    }
    w !,"Final Fetch SQLCODE: ",SQLCODE
    &sql(
        CLOSE EmpCursor
    )
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}

下面的嵌入式SQL示例显示了一个无参数的FOR循环调用FETCH,从名为EmpCursor的游标检索数据。
INTO子句被指定为FETCH语句的一部分:

ClassMethod FETCH2()
{
    &sql(
        DECLARE C1 CURSOR FOR 
            SELECT Name,Home_State INTO :name,:state FROM Sample.Person
            WHERE Home_State %STARTSWITH 'M'
    )
    &sql(OPEN C1)
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    &sql(FETCH C1)
    while (SQLCODE = 0) {
        w "count: ",%ROWCOUNT," RowID: ",%ROWID,!
        w "  Name=",name," State=",state,!
        &sql(FETCH C1) 
    }
    w !,"Final Fetch SQLCODE: ",SQLCODE
    &sql(CLOSE C1)
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}

下面的嵌入式SQL示例显示FETCH检索聚合函数值。
%ROWID没有设置:

ClassMethod FETCH3()
{
    &sql(
        DECLARE PersonCursor CURSOR FOR 
        SELECT COUNT(*),AVG(Age) FROM Sample.Person 
    )
    &sql(OPEN PersonCursor)
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    n %ROWCOUNT
    for { 
        &sql(
            FETCH PersonCursor INTO :cnt,:avg
        )
        q:SQLCODE'=0  
        w %ROWCOUNT," Num People=",cnt," Average Age=",avg,! 
    }
    w !,"Final Fetch SQLCODE: ",SQLCODE
    &sql(CLOSE PersonCursor)
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}

下面的嵌入式SQL示例显示FETCH检索DISTINCT值。
%ROWID没有设置:

ClassMethod FETCH4()
{
    &sql(
        DECLARE EmpCursor CURSOR FOR 
        SELECT DISTINCT Home_State FROM Sample.Employee
        WHERE Home_State %STARTSWITH 'M'
        ORDER BY Home_State 
    )
    &sql(OPEN EmpCursor)
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    n %ROWCOUNT
    for { 
        &sql(
            FETCH EmpCursor INTO :state
        )
        q:SQLCODE'=0  
        w %ROWCOUNT," State=",state,! 
    }
    w !,"Final Fetch SQLCODE: ",SQLCODE
    &sql(CLOSE EmpCursor)
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}

下面的嵌入式SQL示例显示了游标跨名称空间持久存在。
该游标在%SYS中声明,在USER中打开和获取,在SAMPLES中关闭。
注意,OPEN必须在包含要查询的表的名称空间中执行,FETCH必须能够访问输出主机变量,这些变量是特定于名称空间的:

ClassMethod FETCH5()
{
    &sql(USE DATABASE %SYS)
    w $ZNSPACE,!
    &sql(DECLARE NSCursor CURSOR FOR SELECT Name INTO :name FROM Sample.Employee)
    &sql(USE DATABASE "USER")
    w $ZNSPACE,!
    &sql(OPEN NSCursor)
    if SQLCODE<0 {
        w "SQL Open游标错误:",SQLCODE," ",%msg  
        q
    }
    n SQLCODE,%ROWCOUNT,%ROWID
    for { 
        &sql(FETCH NSCursor)
        q:SQLCODE  
        w "Name=",name,! 
    }
    &sql(USE DATABASE SAMPLES)
    w $ZNSPACE,!
    &sql(CLOSE NSCursor)
    if SQLCODE<0 {
        w "SQL关闭游标错误:",SQLCODE," ",%msg  
        q
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容