• 沒有找到結果。

第八章 数据库编程

N/A
N/A
Protected

Academic year: 2022

Share "第八章 数据库编程"

Copied!
70
0
0

加載中.... (立即查看全文)

全文

(1)

第八章 数据库编程

思考:SQL语言有什么缺陷?

(2)

本章内容

应用系统如何对数据库进行操作

嵌入式SQL

存贮过程

SQL/API (Application Programming

Interface)一组函数和程序 SQL/CLI:

“Call-Level Interface”从宿主语言 主程序中调用一个SQL DBMS库,而SQL 语句是这个调用的参数。

ODBC

JDBC

(3)

SQL 概述——嵌入式SQL

将SQL语句嵌入到高级语言(宿主语言)

使应用程序充分利用SQL访问数据库的能 力、宿主语言的过程处理能力

需要预编译,将嵌入的SQL语句转化为宿

主语言编译器能处理的语句

(4)

嵌入式SQL —— 系统实现

实现框图:

主语言+ 嵌入式 SQL 预处理

主语言+ 函数调用

主语言编译器 SQL library

目标代码程序

(5)

嵌入式SQL

将SQL访问数据库的能力,与宿主语言的 过程化处理的能力进行综合

将SQL语句嵌入宿主语言中

产生的问题:

1)宿主语言如何识别SQL语句?

2)SQL语句如何识别宿主语言变量?

3)如何进行数据交换?

4)集合操作如何转换为记录操作?

(6)

嵌入式SQL——形式

SQL语句加上前缀,区别于宿主语言的语句

Exec Sql <sql语句>;

ex.:Exec sql Delete From Student;

预编译

将具有前缀的语句,转换成宿主语言的调用语句

由宿主语言的编译器生成目标码

(7)

嵌入式SQL——SQLCA

SQLCA——SQL Communication Area

sql通讯区域

数据库工作单元 ←→宿主语言工作单元之间的通 讯区域

宿主语言 →DB:请求、参数

DB→宿主语言:执行的状态信息、出错信息

DB→宿主语言:(查询)执行的结果

(8)

嵌入式SQL——SQLCA

Sqlca.sqlcode (Sybase 数据库):

error code

0: success

< 0 : fail

100: row not found

Sqlca.sqlstate:

标准(ISO)返回信息码

00000: no error

02000: could not be found

(9)

嵌入式SQL——变量

SQL语句如何识别宿主语言的变量 ?

主变量(共享变量 )

宿主语言语句

嵌入的SQL语句

SQL语句中主变量前加冒号:作为标志

宿主变量

仅用于宿主语言的语句中

(10)

嵌入式SQL——变量

主变量的定义

Exec Sql Begin Declare Setction;

Exec Sql End Declare Setction;

(11)

嵌入式SQL——游标(Cursor)

数据库操作的结果分为单记录和多记录

单记录:变量 select…into…

多记录:游标(游标的定义,打开和关闭 )

游标的作用:将多行数据集转换为单行数据

便于宿主语言处理

(12)

嵌入式SQL——结构

由宿主语言处理数据

宿主变量

共享变量

由内嵌的SQL语句处理数据库的访问

共享变量

(13)

嵌入式SQL——结构

……

Exec sql Include Sqlca;

Exec sql Begin declare Section;

Char sno(5);

Char cno(3);

Int grade;

Exec sql End Declare Section;

main(){

Exec sql Declare C1 Cursor For Select sno,cno,grade

From SC;

Exec sql Open C1;

For(;;){

Exec sql Fetch C1 into :sno,:cno,:grade if(sqlca.sqlcode <> SUCCESS)

break;

printf(“sno:%s,cno:%s:%d”,sno,cno,grade);

}

Exec sql Close C1;

}

光标的定义,打开和关闭

(14)

嵌入式SQL——简单操作

说明性语句

数据定义语句

数据控制语句

涉及单行的数据操纵语句

(15)

嵌入式SQL——简单操作

说明性语句

Exec sql Begin Declare Setcion;

……

Exec sql End Declare Setcion;

(16)

嵌入式SQL——简单操作

涉及变量的处理

变量名以‘ :’标识,区别于数据库中的对象(表

名、视图名、属性名 …...)

(17)

嵌入式SQL——简单操作

查询

Select …

Into <共享变量名>[<指示变量>],…

From … Where …

Group By … Having … Order By ...

指示变量:用来指示所指的 主变量的值或条件,例如主 变量是否为空值?是否被截 断?

(18)

嵌入式SQL——简单操作

Exec sql Select sno,cno,grade Into :sno,:cno,:grade:grade_id From sc

Where sno = :given_sno and cno = :given_cno;

<0示grade为Null 指示变量

(19)

嵌入式SQL——游标的使用

对象

返回多行数据的查询结果集

根据查询结果修改或删除单个元组的操作

(Current形式)

(20)

嵌入式SQL——游标的使用

方法

定义游标

Exec sql Declare <游标名> Cursor For <查询块>;

打开游标

Exec sql Open <游标名>; //执行查询

//定位于第一行的前一行

移动指针/获取数据

Exec sql Fetch <游标名> Into <共享变量名> <指示变量 名>,...

(21)

嵌入式SQL——游标的使用

判断是否到底

sqlca.sqlcode

关闭游标

Exec sql Close <游标名>;

(22)

嵌入式SQL——游标的使用

Current 形式的 Update

定义游标

Exec sql Declare <游标名> Cursor for

<查询块> For Update Of <属性名>;

打开游标

Fetch游标

Update

Exec sql Update ……Where Current Of <游标名>

(23)

嵌入式SQL——游标的使用

Current 形式的 Delete

定义游标

Exec sql Declare <游标名> Cursor for <查询块>;

打开游标

Fetch游标

Delete

Exec sql delete From … Where Current Of <游标名>

(24)

嵌入式SQL——动态SQL

SQL 语句在编译时未知

在运行时才知道

(25)

嵌入式SQL——动态SQL

主语言程序:

接受用户输入的字符串

转换成可执行的SQL语句 两种方式:

Exec Sql Prepare <query name> FROM <text of the query>;

Exec Sql execute <query name>;

Exec Sql Execute Immediate <text of the query>;

(26)

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通信区*/

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

(27)

int main(void) /*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,指向查询结果的第一 */

(28)

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');

(29)

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; /*断开数据库连接*/

}

(30)

过程化SQL

关系数据库管理系统自己的 过程化语言

例如:Oracle PL/SQL, Microsoft SQL

Server 的 Transact-SQL, IBM DB2 的SQL

PL 等

(31)

过程化SQL 基本结构

定义部分

DECLARE 变量,常量,游标等

执行部分 BEGIN

SQL语句,过程化语句, 异常处理部分

END

(32)

过程化SQL的用处

SQL2003标准给出了基于过程化 SQL ,来实现:

存贮过程

函数

(33)

PL/SQL: 数据库过程化语言

基本结构

定义部分 DECLARE

变量,常量,异常等说明

执行部分 BEGIN

EXCEPTION

END

(34)

PL/SQL: 数据库过程化语言

变量常量的定义

• 变量定义: 变量名 数据类型[NOT NULL]:初值 表达式

• 常量定义: 常量名 数据类型 CONSTANT:=常 量表达式

赋值语句

• 变量名称:=表达式

(35)

PL/SQL: 数据库过程化语言

各种控制语句

IF … THEN …END IF

IF … THEN … ELSE … END IF

LOOP … END LOOP

WHILE … END LOOP

FOR… IN… LOOP … END LOOP

(36)

存贮过程的创建,执行和删除

CREATE Procedure 过程名([参数1,参数 2,…]) AS <PL/SQL>块

CALL/PERFORM Procedure过程名(参数列 表) 或EXEC SQL CALL Procedure 过程 名

DROP PROCEDURE 过程名()

(37)

存贮过程的实例

CREATE PROCEDURE TRANSFER (inAccount INT,outAccount INT,amount FLOAT) AS DECLARE

/*定义存储过程TRANSFER,其参数为转入账户、转

出账户、转账额度*/

totalDepositOut FLOAT totalDepositIn Float;

inAccountnum INT;

BEGIN ….. END

(38)

存贮过程的实例 (续)

BEGIN /*检查转出账户的余额 */

SELECT Total INTO totalDepositOut FROM Account WHERE accountnum=outAccount;

IF totalDepositOut IS NULL THEN

/*如果转出账户不存在或账户中没有存款*/

ROLLBACK; /*回滚事务*/

RETURN;

END IF;

(39)

存贮过程的实例 (续)

IF totalDepositOut< amount THEN /*如果账户存款不足*/

ROLLBACK; /*回滚事务*/

RETURN;

END IF;

SELECT Accountnum INTO inAccountnum FROM Account WHERE accountnum=inAccount;

IF inAccounum IS NULL THEN /*如果转入账户不存在*/

ROLLBACK; /*回滚事务*/

RETURN;

ENDIF;

(40)

存贮过程的实例 (续)

UPDATE Account SET total=total-amount WHERE accountnum=outAccount;

/* 修改转出账户余额,减去转出额 */

UPDATE Account SET total=total + amount WHERE accountnum=inAccount;

/* 修改转入账户余额,增加转入额 */

COMMIT; /* 提交转账事务 */

END;

(41)

存贮过程的优点

运行效率高.提供在服务器端快速执行SQL语 句的有效途径.

降低客户机和服务器之间的通信量.

方便实施企业规则

执行:

CALL Procedure TRANSFER(0100388111,

2333999,1000)

(42)

函数

 函数的定义

CREATE FUNCTION <name> (<parameters>) RETURNS <type> AS < local declarations function body>;

 函数的执行

作为一个表达式放到适合返回值的地方.

 修改函数

ALTER FUNCTION 函数名1 rename to 函数名2

(43)

课堂练习

存贮过程

实现学生通过课程名来搜索该课程信息

Create procedure searchByCname(IN course_name char(10)) as

Select C.CID, C.cname, C.teacher from courses C

Where C.cname=course_name

(44)

调用该存贮过程

在交互式环境中

CALL searchByCname(Database)

在嵌入式环境中

EXEC SQL BEGIN DECLARE SECTION CHAR coursename[10]

EXEC SQL END DECLARE SECTION

EXEC SQL CALL seachByCname(:coursename)

(45)

SQL/API 的样例

#include “sqlcli.h”

SQLHSTMT hstmt;

SQLPrepare(hstmt,“Insert Into customer values(……)”);

SQLExcute(hstmt);

是微软公司开放服务体系(Windows Open Services Architecture,WOSA)中有关数据库的一个组成部分

提供了一组访问数据库的应用程序编程接口(Application Programming Interface,API )

(46)

ODBC 工作原理

请求连接数据库

发送SQL语句

为结果分配存贮 空间

获取执行结果或 错误信息

进行数据处理并 提交结果

事务提交或回滚

断开连接

用户应用程序

ODBC API 标准接口 驱动程序管理器

DRIVER 1 DRIVER 2 DRIVER3 Sybase Oracle

DB2

(47)

应用场景

假设某个学校在SQL Server和KingbaseES上创 建了两个数据库:学校人事数据库和教学科研 数据库。

学校的信息系统要从这两个数据库中存取数据

为了方便地与两个数据库连接,为学校人事数据库 创建一个数据源名PERSON,为教学科研数据库创建 一个名为EDU的数据源

当要访问每一个数据库时,只要与PERSON和EDU连

接即可,不需要记住使用的驱动程序、服务器名称、

数据库名 。

(48)

ODBC 数据结构

Environments : represent the DBMS installation. (环境句柄)

Connections : (连接句柄)logins to the database.

Statements : (语句句柄) SQL statements to be passed to a connection.

Descriptions :描述符句柄 ,描述SQL语句 的参数,结果集的元数据集合

句柄是32位整数值,代表一个指针

(49)

应用程序句柄之间的关系

ODBC 应用程序

环境句柄 (1:1)

连接句柄 (1:n)

(1:1) (1:n) (1:n)

数据源 语句句柄 描述符句柄

(50)

ODBC 的工作流程

(51)

JDBC

JAVA 作为主语言

Java Database Connectivity (JDBC) 是

一个库,定义SQL嵌入到JAVA的一系列函数

(52)

驱动器管理与连接到数据源

import java.sql.*;

Class.forName(com.mysql.jdbc.Driver);

Connection myCon =

DriverManager.getConnection(…);

The JDBC classes

加载mySql驱动器;

URL of the database

your name, and password go here.

Loaded by forName

(53)

执行SQL语句

JDBC 有两种类型的语句类:

1.

Statement = an object 可以有一

个SQL语句作为参数,也可以没有。

2.

PreparedStatement = an object

已经有了一个SQL语句作为参数。

(54)

创建语句

The Connection class 有方法来创建 Statement 和 preparedStatement.

Statement stat1 = myCon.createStatement();

PreparedStatement stat2 = myCon.createStatement(

”SELECT sid, sname FROM Students ” + ”WHERE Sdept=‘cs’ ”

);

createStatement 不带参数,返回

a Statement 对象; 带参数,则返回 a PreparedStatement 对象.

(55)

执行 SQL 语句

JDBC 查询和更新是不同的。

Statement 和 PreparedStatement 对象有 方法 executeQuery 和 executeUpdate.

Statements类对象: 需要参数才可以查询或更 新。

PreparedStatements对象: 不需要属性。

(56)

举例:更新

stat1 是一个 Statement类对象:

stat1.executeUpdate(

”INSERT INTO Students ” +

”VALUES(01111,’Brass Rail’,25)”

);

(57)

举例:查询

stat2 是一个PreparedStatement对象,已经 有参数,即查询语句 “ SELECT sid, sname FROM Students WHERE Sdept=‘cs’ ”。

executeQuery 返回一个ResultSet 类对象。

ResultSet CSstudents =

stat2.executeQuery();

(58)

存取结果集

ResultSet类型的对象像一个光标。

该类型对象有方法:Method next() 会 把光标移到下一个,如果结束,

next() 返回 值 false.

(59)

存取元组中的分量

ResultSet 对象存取某一个分量,使用:

Method get X ( i ), X 是某种类型, i 是第几个分量,它的类型是 X . 例如:

getString(1), getFloat(2)

(60)

举例:存取元组分量

CSstudents 是ResultSet对象

是查询句 “ SELECT sid, sname FROM Students WHERE Sdept=‘cs’ ”的结果。

while ( CSstudents.next() ) { SID = Menu.getString(1);

Sname = Menu.getString(2);

/*对变量 SID 以及Sname 处理*/}

(61)

小结: 数据库编程

嵌入式SQL: 把SQL嵌入到传统编程语 言中.

存贮过程/函数: 提供一种标准的面向 SQL的编程语言.

数据库之间互相连接的规范(一组函

数): ODBC,JDBC

(62)

作业

课堂作业:PYTHON和SQLite语言如何结合?

(63)

答案:一般步骤

# import sqlite3 module

import sqlite3

# create a connection object

conn = sqlite3.connect('<DBname>.<db/sqlite/db3>')

# create a cursor object

cur = conn.cursor()

# call the cursor's execute() method to perform SQL commands

cur.execute('<SQL statement>')

# save (commit) the changes

conn.commit()

# close the connection

conn.close()

(64)

课堂作业

用Python实现和mydb数据库的连接,并执 行如下查询语句:

1.

查找年龄小于25岁的学生,并按年龄排序

2.

查找每个系学生的最大年龄

(65)

创建一个表

65

• Triple-quotes – for string literals that span multiple lines.

• We need to commit once we are certain about the changes.

In SQLite3, before committing, a journal file is maintained.

cur.execute('''DROP TABLE IF EXISTS students;''') cur.execute('''CREATE TABLE students(

sid int PRIMARY KEY,

name char[10] NOT NULL, dept char[2],

age int DEFAULT 20); ''') conn.commit()

(66)

插入

cur.execute('''INSERT INTO students

VALUES(?,?,?,?)''', (1,'smith','cs',35))

conn.commit()

Use “?” as a placeholder and

provide the values in a tuple

(67)

插入多个元组

tmp = [(2,'martin','cs',20),

(3,'Bern','cs',28),

(4,'Hone','cs',23),

(5,'Lihong','ee',18),

(6,'John','ee',29),

(7,'Flower','ee',25),

(8,'martin','ee',20),

(9,'smith','ma',21),

(10,'wang','ma',19)]

cur.executemany('INSERT INTO students VALUES(?,?,?,?)', tmp)

conn.commit()

Batch insert multiple rows,

preparing the tuples of values in a list and call

cur.executema ny()

(68)

删除

cur.execute('DELETE FROM students WHERE age > 30')

conn.commit()

(69)

修改

cur.execute('''UPDATE students

SET age = 17

WHERE name = 'martin' AND dept = “cs”

''')

conn.commit()

(70)

70

查询

cur.execute('''SELECT * FROM students

WHERE age < 25 ORDER BY age ''')

for row in cur:

print row

• To retrieve data after executing a SELECT statement, the cursor can be treated as an iterator.

cur.execute('''SELECT dept, MAX(age)

FROM students GROUP BY dept ''')

for row in cur:

print "dept. = ", row[0]

print "MAX(age) = ", row[1], "\n"

參考文獻

相關文件

int main(int argc, char** argv).

七、考生除必備文具、無色透明無文字墊板、手錶外,不得攜帶其他任何妨害考試公平

public static double calculate(int i, int j) throws ArithmeticException,

 Transfer the P-CSCF address with the PDP Context Activation signaling to the UE. GGSN acts as a DHCP Relay Agent 1.Create PDP context bearer ( TS 23.060) 2.UE requests a

and Peterson, G., “Convective Heat Transfer and Flow Friction for Water Flow in Microchannel Structures,” Int. Heat and Mass

Pollard, 1996, “Heat transfer in separated and impinging turbulent flows”, International Journal of Heat Mass Transfer, Vol.. Mistry, 2001, “Impingement heat transfer in

public class Student { private String name;.. private

,在需求分析过程中应该建立起软件系统的 行为模型。状态转换图 ( 简称为状态图 ) 通