数据库编程和嵌入式SQL

数据库编程和嵌入式SQL

Abstract

  • 主语言
  • 预编译

exec

  • C下时在SQL语句前加exec sql标识.
  • Java使用#sql{};

SQL和主语言的通信

Abstract

  1. 传递SQL语句的执行状态信息,使用SQL通信区
  2. 向SQL Server提供参数 通过主变量实现.
  3. 将查询结果回传 使用主变量和游标

主变量

SQL中使用的主语言的变量进行查询更新等操作使用的变量.

  • 输入主变量
  • 输出主变量

指示变量:int,一个主变量可以附带一个指示变量,用于指示主变量的值或状态.比如是否为空,是否截断等.

主变量和指示变量在SQL语句中说明

范例:

BEGIN DECLARE SECTION
-- VIRABLE...
-- ...
END DECLARE SECTION

主变量可以出现在任何一个使用表达式的地方,前面加:作区别.

指示变量也要加冒号,并且紧跟在主变量之后.

游标

系统开设的缓冲区,存放执行结果.SQL语句会产生多条记录,而主变量只能储存一条.

每个游标区都有名字,可以通过游标获取记录.

SQL通信区

SQLCA是一个数据结构,储存1.系统工作状态2.描述运行环境

应用程序从SQL通信区取出信息,决定执行语句.

SQLCA定义

EXEC SQL INCLUDE SQLCA

struct SQLCA
{
	SQLCODE;//存放每次执行之后返回代码的变量,0=success,100=no rows,-1=failed
	//...
}

建立/关闭连接

EXEC SQL CONNECT TO <SERVER><CONNECTION-NAME><USERNAME>

程序运行过程中可以修改当前连接

只有一个连接时可以不指定.

EXEC SQL DISCONNECT <CONNECTION-NAME>

关闭.

Simple Instance

依次检查某个系的学生记录,交互式更新 某些学生年龄。

EXEC SQL BEGIN DECLARE SECTION; /*主变量说明开始*/ 
char Deptname[20]; 
char Hsno[9]; 
char Hsname[20];
char Hssex[2]; 
int HSage;
int NEWAGE; 
EXEC SQL END DECLARE SECTION; /*主变量说明结束*/ 

long SQLCODE;
EXEC SQL INCLUDE SQLCA; /*定义SQL通信区*/  



int main() /*C语言主程序开始*/
{
    int count = 0;
    char yn; /*变量yn代表yes或no*/
    printf("Please choose the department name(CS/MA/IS): ");
    scanf("%s",deptname); /*为主变量deptname赋值*/
    EXEC SQL CONNECT TO TEST@localhost:54321 USER "SYSTEM"/"MANAGER"; /*连接数据库TEST*/
    EXEC SQL DECLARE SX CURSOR FOR /*定义游标SX*/ 
    SELECT Sno,Sname,Ssex,Sage /*SX对应的语句*/ 
    FROM Student WHERE SDept = :deptname; EXEC SQL OPEN SX; /*打开游标SX,指向查询结果的第一行*/ 
    for ( ; ; ) /*用循环结构逐条处理结果集中的记录*/ 
    {
        EXEC SQL FETCH SX INTO :HSno,:Hsname,:HSsex,:HSage; /*推进游标,将当前数据放入主变量*/ 
        if (SQLCA.SQLCODE!= 0) /*SQLCODE != 0,表示操作不成功*/ 
            break; /*利用SQLCA中的状态信息决定何时退出循环*/ 
        if(count++ == 0) /*如果是第一行的话,先打出行头*/
            printf("\n%-10s %-20s %-10s %-10s\n", "Sno","Sname","Ssex", "Sage");
        printf("%-10s %-20s %-10s %-10d\n“, HSno,Hsname,Hssex,HSage); /*打印查询结果*/
        printf("UPDATE AGE(y/n)?"); /*询问用户是否要更新该学生的年龄*/
        do
        	{scanf("%c",&yn);} 
        while(yn != 'N' && yn != 'n' && yn != 'Y' && yn != 'y'); 
        if (yn == 'y' || yn == 'Y') /*如果选择更新操作*/ 
        { 
            printf("INPUT NEW AGE:"); scanf("%d",&NEWAGE); /*用户输入新年龄到主变量中*/
            EXEC SQL UPDATE Student /*嵌入式SQL更新语句*/ 
            SET Sage = :NEWAGE WHERE CURRENT OF SX; 
        } /*对当前游标指向的学生年龄进行更新*/
      } 
      EXEC SQL CLOSE SX; /*关闭游标SX,不再和查询结果对应*/ 
      EXEC SQL COMMIT WORK; /*提交更新*/ 
      EXEC SQL DISCONNECT TEST; /*断开数据库连接*/ 
 } 

游标的使用

不使用游标的:

  • 说明语句
  • 数据定义
  • 数据控制
  • 查询结果为单记录的
  • CURRENT的增删改

只使用主变量,使用INTO指定.

单记录的SELECT

E.g.

EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept
	INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
	FROM Student
	WHERE Sno=:givensno;

如果不是单条记录,则出错并在SQLCA中返回错误信息

指示变量的使用:

EXEC SQL SELECT Sno,Cno,Grade
	INTO :Hsno,:Hcno,:Hgrade:Gradeid
	/*指示变量Gradeid*/
	FROM SC
	WHERE Sno=:givensno AND Cno=:givencno;

指示变量的作用:如果Gradeid < 0,不论Hgrade为何值,均认为该学生成绩为空值。防止错误信息扩散

非CURRENT的增删改

UPDATE中的SETWHERE可以使用主变量,SET可以使用指示变量.

E.g.

EXEC SQL UPDATE SC
	SET Grade=:newgrade
	/*修改的成绩已赋给主变量:newgrade*/
	WHERE Sno=:givensno;
	/*学号赋给主变量:givensno*/

E.g.2

gradeid=-1/*gradeid为指示变量,赋为负值*/
EXEC SQL INSERT
	INTO SC(Sno,Cno,Grade)
	VALUES(:stdno,:couno,:gr :gradeid)/*:stdno,:couno,:gr为主变量*/

由于该学生刚选修课程,成绩应为空,所以要把指示变量赋为负值(负值表示空或出错)


使用游标的:

  • 查询结果为多条语句的
  • CURRENT的增删

多条语句结果的查询

声明游标

EXEC SQL DECLARE <CURSORNAME> CURSOR FOR <SELECT...>

此时并不执行select语句

打开游标

EXEC SQL OPEN <CURSORNAME>

执行预定义的SELECT 语句,查询结果取到缓冲区中.此时游标开始活动,指向第一条记录.

推进指针(TO NEXT)

EXEC SQL FETCH <CURSORNAME> INTO :<MAINVAR>[:<STATUSVAR>],....

FETCH用于推进执行下一条并用于更新主变量.

循环使用FETCH逐个取出

游标关闭

EXEC SQL CLOSE <NAME>

关闭游标对查询结果集的联系.可以重新打开和(更)新的结果联系.

CURRENT UPDATE/DELETE

修改SELECT语句的结果的某几条结果.

WHERE CURRENT OF <CURSORNAME>

发布了80 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/POTASSIUM711/article/details/102692944