博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【SQL】宿主语言接口
阅读量:6039 次
发布时间:2019-06-20

本文共 3963 字,大约阅读时间需要 13 分钟。

一般情况下,SQL语句是嵌套在宿主语言(如C语言)中的。有两种嵌套方式:

1.调用层接口(CLI):提供一些库,库中的函数和方法实现SQL的调用

2.直接嵌套SQL:在代码中嵌套SQL语句,提交给预处理器,将SQL语句转换成对宿主语言有意义的内容,如调用库中的函数和方法代替SQL语句

 

阻抗不匹配问题:连接SQL语句与常规编程语言的基本问题。SQL核心使用关系数据模型,而C语言等常规语言则使用整型、实数型、算数型、字符型、指针等类型。

 

 

一、SQL与宿主语言连接

EXEC SQL关键字提示预处理将由SQL代码进入。

共享变量:实现数据库和宿主语言之间的信息交换。

SQL中共享变量要加冒号,宿主语言中不需要。

SQLSTATE:特殊变量,由5个字符的数组组成(在C中分配空间要分配6个,后面有'\0'),存放表示调用过程出现的问题的代码。'00000'表示没有错误。

1.1 DECLARE节

声明共享变量要在声明节中。

EXEC SQL BEGIN DECLARE SECTION;

...

EXEC SQL END DECLARE SECTION;

 

EXEC SQL BEGIN DECLARE SECTION;    char studioName[50], studioAddr[256];    char SQLSTATE[6];EXEC SQL END DECLARE SECTION;

 

1.2 使用共享变量

任何不含返回结果的SQL语句,都可以用EXEC SQL为前缀嵌入宿主语言。

 

void getStudio(){    EXEC SQL BEGIN DECLARE SECTION;        char studioName[50], studioAddr[256];        char SQLSTATE[6];    EXEC SQL END DECLARE SECTION;    printf("please input studio name:\n");    scanf("%s", &studioName);    printf("please input studio address:\n");    scanf("%s", &studioAddr);    EXEC SQL INSERT INTO Studio(name, address)                    VALUES (:studioName, :studioAddr);

 

 

 

1.3 连接SQL返回结果到宿主语言

因为阻抗不匹配,使得返回结果无法直接返回到宿主语言中,必须使用下面两种机制中的一个。

单元组选择语句:只有一个结果的查询语句,将该元组存储到共享变量中。

游标:为查询声明一个游标,游标范围覆盖结果关系中的所有元组,每个元组一次被提取到共享变量,由宿主语言处理。

1.4单元组选择语句

类似于普通的select-from-where语句,只是SELECT子句后面紧跟着关键字INTO和一连串的共享变量。如果结果少于或多于一个元组,则共享变量中不会有值,且SQLSTATE中存入一个错误码。

 

void printNetWorth(){    EXEC SQL BEGIN DECLARE SECTION;        char studioName[50];        int presNetWorth;        char SQLSTATE[6];    EXEC SQL END DECLARE SECTION;    /*输入studioName的代码*/    EXEC SQL SELECT netWorth                    INTO :presNetWorth                    FROM Studio, MovieExec                    WHERE presC# = cert# AND                                Studio.name = :studioName;    /*检查SQLSTATE中的代码是否为'00000'*/}

 

 

1.5 游标

游标声明:

EXEC SQL DECLARE 游标名称 CURSOR FOR 查询

初始化游标的位置:使之指向第一个元组

EXEC SQL OPEN 游标名称

得到下一个元组:

EXEC SQL FETCH FROM 游标名称 INTO 变量列表

变量列表中存放获取的结果,如果已经遍历结束则SQLSTATE中返回'02000'

关闭游标:

EXEC SQL CLOSE 游标名称

 

void worthRanges(){    int i, digits, counts[15];    EXEC SQL BEGIN DECLARE SECTION;        int worth;        char SQLSTATE[6];    EXEC SQL END DECLARE SECTION;    EXEC SQL DECLARE execCursor CURSOR FOR            SELECT netWorth FROM MovieExec;    EXEC SQL OPEN execCursor;    for(i = 1; i < 15; i++)        counts[i] = 0;    while(1){        EXEC SQL FETCH FROM execCursor INTO :worth;        if(NO_MORE_TUPLES)             break;        digits = 1;        while((worth /= 10) > 0) digits++;        if(digits <= 14) counts[digits]++;    }    EXEC SQL CLOSE execCursor;    for(i = 1; i < 15; i++)        printf("digits = %d: number of execs = %d\n",i, counts[i]);}

 

1.6 游标更新

可以通过游标删除或修改当前的元组。

WHERE后只能是 WHERE CURRENT OF

下面的例子将资产少于1000的删除,多余1000的翻倍。

 

#define NO_MORE_TUPLES !(strcmp(SQLSTATE,"02000"))void changeWorth(){    EXEC SQL BEGIN DECLARE SECTION;        int certNo, worth;        char execName[31], execAddr[256], SQLSTATE[6];    EXEC SQL END DECLARE SECTION;    EXEC SQL DECLARE execCursor CURSOR FOR MovieExec;    EXEC SQL OPEN execCursor;    while(1){        EXEC SQL FETCH FROM execCursor INTO :execName, :execAddr, :certNo, :worth;        if(NO_MORE_TUPLES) break;        if(worth < 1000)            EXEC SQL DELETE FROM MovieExec                                         WHERE CURRENT OF execCursor;        else            EXEC SQL UPDATE MovieExec                            SET netWorth = 2 * netWorth                            WHERE CURRENT OF execCursor;    }    EXEC SQL CLOSE execCursor;}

 

 

 

1.7 避免并发修改

如果在游标获取到元组到游标关闭前,不希望元组发生变化:

EXEC SQL DECLARE 游标名 INSENSITIVE CURSOR FOR 查询;

不希望通过游标修改元组

EXEC SQL DECLARE 游标名  CURSOR FOR 查询 FOR READ ONLY

 

1.8动态SQL

在运行时,通过输入SQL语句实现查询需要动态SQL语句支持。

EXEC SQL PREPARE V FROM 表达式;

EXEC SQL EXECUTE V; //这句可以多次执行 表明表达式V执行了多次

上面两句合并后可以写成:

EXEC SQL EXECUTE IMMEDIATE 表达式;

 

void readQuery(){    EXEC SQL BEGIN DECLARE SECTION;        char * query;    EXEC SQL END DECLARE SECTION;    /*输入SQL语句,放入query中*/    EXEC SQL PREPARE SQLquery FROM :query;    EXEC SQL EXECUTE SQLquery;}

 

转载地址:http://iirhx.baihongyu.com/

你可能感兴趣的文章
kafka生产消息的速度跟什么有关?
查看>>
Web API 简介
查看>>
Jexus下配置多个站点
查看>>
mysql case when * else end
查看>>
C#中==与Equals方法的区别
查看>>
「珍藏」老司机为你推荐10个炫酷的开源库,看完的人都收藏了
查看>>
Xcode编辑器的技巧与诀窍
查看>>
String、StringBuffer与StringBuilder之间区别
查看>>
工作第十三周:身体掏空,精神饱满
查看>>
Linux 内核--任务0的运行(切换到用户模式)move_to_user_mode
查看>>
ios扩展机制objc_setAssociatedObject,objc_getAssociatedObject
查看>>
批量添加-fno-objc-arc
查看>>
二叉树的层序遍历
查看>>
os模块
查看>>
安装 matplotlib
查看>>
css伪类(:before和:after)
查看>>
react native TypeError network request failed
查看>>
【转】CentOS 7. × 系统及内核升级指南
查看>>
PLSQL锁表之后改如何操作
查看>>
LeetCode(92):Reverse Linked List II
查看>>