嵌入式SQL

本文深入探讨了嵌入式SQL的概念及其与交互式SQL的区别,详细介绍了如何在C语言中使用嵌入式SQL进行数据库操作,包括连接数据库、执行SQL语句、处理查询结果等,并讨论了动态SQL的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

交互式SQL语言的局限性

从使用者角度

普通用户必须通过数据库应用程序来使用
使用者角度

从SQL本身角度

特别复杂的检索结果难以用一条交互式SQL语句完成,此时需要结合高级语言中经常出现的顺序,分支和循环结构帮助处理

嵌入式SQL特性

定义

嵌入式SQL是将SQL嵌入到某一种高级语言之中,如C/C++,Java等 这种高级语言被称为宿主语言

特性
  1. 继承了高级语言的过程控制性
  2. 结合了SQL语言的复杂结果集操作的非过程性
  3. 为数据库操作者提供了安全可靠的操作方式:通过应用程序进行操作
和交互式SQL的对比

交互式: select Sname,Sage from Student Where Sname=’张三';
嵌入式(此文宿主语言为C): exec sql select Sname,Sage into :vSname.:vSage from Student where Sname="张三";

  • exec sql:引导SQL语句,提供给C编译器,以便对SQl语句预编译成C编译器可识别的语句
  • into子句: 用于指出接收SQL语句检索结果的程序比那里

高级语言–>嵌入式SQL–>DBMS<—->DB

知识点

宿主语言如何与数据库连接

在嵌入式SQl程序执行之前,首先要与数据库进行连接
连接:exec sql connect to target-server as connect-name user user-name ; or exec sql connect to default;
在嵌入式SQL程序执行之后,需要和数据库断开连接
断开连接:exec sql disconnect connect-name; or exec sql disconnect current;

如何将宿主语言的变量传递给SQL语句

变量声明:

exec sql begin declare section;
     char vSname[10],specName[10]="张三"
     int vSage;
exec sql end declare section;

变量使用:变量可传递给SQL语句的where等字句,以便SQL语言能够按照指定的要求进行检索
exec sql select Sname,Sage into :vSname.:vSage from Student where Sname=:specName;

SQL语句如何执行

SQL语句在执行过程中,必须有提交和撤销语句才能确认其操作结果
提交: exec sql commit work
撤销: exec sql rollback work

事务

定义:事务是一个存取或改变数据库内容的程序的一次执行,或者说一条或多条SQL语句的一次执行被看做一个事务,一般由应用程序员提出,有开始和结束,结束前需要提交或撤销
事务的特性:

  • 原子性Atoomicity:DBMS能够保证事务的一组更新操作是原子不可分的,要么全做,要么全不做
  • 一致性Consistency: DBMS保证事务的操作状态是正确的
  • 隔离性Isolation:DBMS保证并发的多个事务之间相互不受影响
  • 持久性Durability:DBMS保证已提交事务的影响是持久的,被撤销事务的影响是可恢复的
如何将SQL检索到的结构传递回宿主程序进行处理
单行结果处理

检索单行结果,可以讲结果直接传送到宿主程序的变量中

exec sql select [ALL|DISTINCT] expression [,expression...]
     INTO host-variable,[host-variable,...]
     From tableref [corr_name][,tableref[corr_name]...]
     Where search_condition;

eg:exec sql select Sname,Sage into :vSname.:vSage from Student where Sname=:specName;

多行结果处理
游标(Cursor)

游标是指向某检索记录集的指针,通过这个指针的移动,每次读一行,处理一行,再读一行,直到处理完毕
读一行的操作是通过Fetch..into实现的,每一次Fetch,都是先向下移动指针,然后再读取,记录集有结束表示EOF,用来标记后面已经没有记录了
游标的使用需要先定义,再打开,接着一条一条处理,最后关闭
Cursor的定义:

EXEC SQL DECLARE cursor_name CURSOR FOR
     Subquery
     [ORDER BY result_column [ASC|DESC][,result_column...]]
     [FOR [READ ONLY |UPDATE [OF columnname[,columnname....]]]]

eg:

exec sql declare cur_student cursor for
     select Sno ,Sname,Sclass from Student where Sclass=:vClass
     order by Sno
     for read only;

Cursor的打开和关闭
打开: exec sql open cursor_name;
关闭: exec sql close cursor_name;

Cursor的数据读取

exec sql fetch cursor_name
     into host-variable,[host-variable,...]

eg:exec sql fetch cur_student into :vSno,:vSname,:vsAGE

数据库的删除与更新
删除

查找删除:exec sql delete from tablename [corr_name] where search_condition
eg:exec sql delete from customers c where c.city='Harbin' and not exists (select * from orders o where o.cid=c.cid)
定位删除:exec sql delete form tablename [corr_name] where current of cursor_name
eg:

exec sql declare delcust cursor for
     select cid from customers c where c.city='harbin' and not exists(select * from orders o where o.cid=c.cid)
     for update of cid;
exec sql open delcust
while(TRUE){
     exec sql fetch delcust into :cust_id;
     exec sql delete from customers where current of delcust;
}
更新

查找删除:exec sql update tablename [corr_name] SET columname= expr [,columname=expr...] where search_condition
eg:exec sql update student s set sclass='035102' where s.sclass=''034101
定位删除:exec sql update tablename [corr_name] SET columname= expr [,columname=expr...] where current of cursor_name
eg:

exec sql declare stud cursor for
     select * from student s where s.class='034101'
     for update of sclass;
exec sql open stud
while(TRUE){
     exec sql fetch stud into :vSno,:vSname,:vSclass;
     exec sql update student  set sclass='035102' where current of stud;
}
插入

插入:exec sql insert into tablename [(columnname[,columnname,...])] [values (expr[,expr,...])|subqurey]
eg:exec sql into student (sno,sname,sclass) values('03510128','张三',‘035101’)

宿主程序如何知道SQL语句的执行状态,是否发生错误

状态:是指嵌入式SQL语句的执行状态,尤其指一些出错状态,有时程序需要知道这些状态并对这些状态进行处理
状态捕获及处理由三部分构成

  • 设置SQL通信区:exec sql include sqlca ,其中SQLCA是一个已被声明过的具有C语言的结构形式的内存信息区,其中的成员变量用来记录SQL语句的执行状态,便于宿主程序读取与处理
  • 设置状态捕获语句:可设置多次,exec sql whenever condition action;该语句会对气候所有由exec sql语句所引起的对数据库系统的调用自动检查它是否满足条件,condition包括 sqlerror;not found;sqlwarning ,action包括continue;goto;stop;do|call,状态捕获语句Whenever的作用范围是其后的所有exec sql 语句,直到程序中出现另一条相同条件的whenever为止
  • 状态处理语句:某一段程序以应对SQL操作的某种状态report_error:exec sqlroollback;
动态SQL,依据条件动态构造SQL语句,但欲访问的表名和字段对编程者是已知的

静态SQL:SQL语句在程序中已经按要求写好,只需要把一些参数通过变量传送给嵌入式SQL语句即可
eg:

SpecName='张三';
exec sql select Sno,Sname,Sclass into :vSno,:vSname,:vSclass from Student where Sname=:SpecName;

动态SQL:SQL语言可以在程序中动态构造,形成一个字符串,然后再交给DBMS执行,交给DBMS执行时仍然可以传递变量

#include <stdio.h>
exec sql include sqlca;

exec sql begin declare section;
     char user_name="Scott"; char user_pwd[]="tiger";
     char sqltext[]="delete from customers where cid=\'c006\'";
exec sql end declare section;

int main()
{
     exec sql whenever sqlerror goto report_error;
     exec sql connect :user_name identified by :user_pwd;
     exec sql execute  immediate :sqltext;
     exec sql commit release: return 0;

     report_error:print_dberror(); exec sql rollback release :return 1;
}

动态SQL的两种执行方式:
1. 立即执行语句(构造的字符串SQL内部没有变量参数):运行时编译并执行 exec sql execute immediate:host-variable;
2. Prepare-Execute-Using语句(构造的字符串内部有变量参数):Prepare语句先编译,编译后的SQL语句允许动态参数,Execute语句执行,用using语句将动态参数传送给编译好的Sql语句

exec sql prepare sql_temp from :host-variable;
-----
exec sql execute sql_temp using :cond-variable;
数据字典(Data dictionary)
  • 定义:是系统维护的一些视图的集合,存储了数据库中各类对象的定义醒醒,这些信息又称数据库的元数据–关于数据的数据
  • 内容:与关系相关的信息;用户与账户信息;统计与描述性数据;物理文件组织信息;索引相关信息

ODBC(open DataBase Connection)

定义:ODBC是一种标准—不同语言的应用程序与不同数据库服务器之间通讯的标准
实现:是一组API,应用程序通过调用ODBC API ,可以实现与数据服务器的连接,向数据库服务器发送SQL命令,一条一条的提取数据库检索结果中的元组传送给应用程序的变量,具体的DBMS提供一套驱动程序,即Driver库函数,供ODBC调用,以便实现数据库与应用系统的连接。
应用程序与数据库连接:
ODBC应用前,需要确认具体的DBMS Driver b被安装到ODBC环境中,当应用程序调用ODBC API时,ODBC API会调用具体DBMS Driver 库函数 ,DBMS Driver 库函数则与数据库服务器通讯,执行相应的请求动作并返回检索结果

  1. ODBC 首先要分配一个SQL环境,再产生一个数据库连接句柄 connection handle
  2. 应用程序使用SQLConnect(),打开一个数据库连接
  3. 使用SQLExecDirect()向数据库发送SQL命令
  4. 使用SQLFetch()获取产生的结果元组
  5. 使用SQLBindCol()绑定C语言变量与结果中的属性

JDBC(Java DataBase Connetion)

JDBC是一组Java版的应用程序接口API,提供了Java应用程序与数据库服务器的连接与通讯能力

### 嵌入式 SQL 的使用方法及示例 嵌入式 SQL 是一种将 SQL 语句嵌入到高级程序设计语言中的技术,通常用于在应用程序中执行数据库操作。以下是关于嵌入式 SQL 的具体用法及其实现细节。 #### 预处理器的作用 为了使嵌入式 SQL 能够被编译器识别并运行,在实际开发过程中需要借助预处理器将嵌入式 SQL 转换为目标编程语言的代码片段[^1]。例如,当开发者在一个 C 或 COBOL 文件中写入嵌入式 SQL 后,预处理器会将其转换为相应的函数调用或其他可由目标语言解释的形式。 #### 数据库连接与环境初始化 在任何涉及嵌入式 SQL 的应用启动之前,都需要完成必要的准备工作,比如建立同数据库服务器之间的通信链路以及设置工作区等参数配置项[^2]。这些步骤对于确保后续查询能够正常运作至关重要。 #### 示例代码展示 (基于C语言) 下面给出一段利用 MySQL Connector/C 实现简单 SELECT 查询功能的例子: ```c #include <mysql.h> #include <stdio.h> int main() { MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; conn = mysql_init(NULL); /* Connect to database */ if (!mysql_real_connect(conn, "localhost", "root", "", "testdb", 0, NULL, 0)) { fprintf(stderr, "%s\n", mysql_error(conn)); return 1; } /* Execute query */ if (mysql_query(conn, "SELECT id,name FROM users")) { fprintf(stderr, "%s\n", mysql_error(conn)); return 1; } res = mysql_use_result(conn); printf("MySQL Tables in mysql database:\n"); while ((row = mysql_fetch_row(res)) !=NULL) printf("%s %s\n", row[0], row[1]); /* close connection and free resources */ mysql_free_result(res); mysql_close(conn); return 0; } ``` 此段代码展示了如何通过 MySQL 提供的 C API 来访问名为 `users` 表格内的记录,并打印每条记录对应的 ID 及姓名字段值[^3]。 #### 性能考量 尽管嵌入式 SQL 方便快捷,但在某些场景下其表现可能不如动态 SQL 理想。这是因为前者往往会在编译期即确定好所有的语法结构,而后者则允许更灵活地构建最终提交给 DBMS 处理的实际命令字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值