四、关系数据库标准语言SQL_3
这里的讲述内容是SQL嵌入C语言,但我会结合MySQL嵌入Python,采用的是PyMySQL这里我的工具会有MySQL,Pycharm。
4.9 嵌入式SQL
主要内容
- 嵌入式SQL概述
- 嵌入式SQL与主语言的接口
- 不用游标的嵌入式SQL
- 用游标的嵌入式SQL
- 嵌入式SQL应用实例
- 动态SQL
- 嵌入式SQL小结
嵌入式SQL概述
-
SQL语言提供了两种不同的使用方式
-
交互式
-
嵌入式
SQL迁入到C,C++,Java,COBOL等程序设计语言中,称为嵌入式SQL(Embedded SQL)。
-
-
宿主语言(主语言)
被嵌入SQL的程序设计语言,称为宿主语言,如C、C++、Java等,称为宿主语言,简称主语言。
-
引入嵌入式SQL的原因
- SQL语言是非过程语言
- 事务处理一般是过程性的,需要应用高级语言
-
将SQL嵌入主语言后
- SQL语句负责数据库的操纵
- 宿主语言负责控制程序流程和数据的输入输出
-
嵌入式SQL和交互式SQL
- 主要命令语句相同
- 实现细节上有所不同
- 嵌入式SQL做了某些必要的扩充
嵌入式SQL与主语言的接口
- 将SQL语句嵌入到宿主语言中必须解决的问题
- 将嵌入主语言的SQL语句编译成为可执行代码
- 数据库和主语言程序间的通信
- 数据库和主语言程序间的数据交换
- 需要协调面向集合和面向记录两种不同的处理方式
1. 嵌入式SQL的编译
SQL与C语言
-
采用预编译方法
- 在编译之前,先对SQL语句进行预处理;
- 通过执行预处理程序把SQL语句编程主语言能够识别的形式;
- 由主语言编译器统一对预处理后的源程序进行编译。
-
预处理要求:
-
所有SQL语句必须加前缀
EXEC SQL
,以区分SQL语句与主语言造句。 -
有的主语言还在SQL语句结尾加上结束标志。
-
在C语言嵌入式SQL的一般格式为:
EXEC SQL <SQL语句>;
-
以COBOL作为主语言的嵌入式SQL语句的一般形式
EXEC SQL <SQL语句> END-EXEC
-
-
嵌入式SQL的C语言源程序的基本编译过程
- 使用预编译器对含有嵌入式SQL语句的C语言源程序进行预处理,把SQL语句变为C语言编译器可识别的命令语句。预处理包括语法检查、存取权限检查、路径选择等。SQL语句处理后生成调用语句。
- 对预处理后的源程序用C编译器进行编译,生成目标代码。
- 连接目标代码,包括C语言库函数和SQL库函数,生成可执行程序。
MySQL与Python
-
采用编译方法(原理)
C 语言中 Python 中的实现 SQL 语句要加 EXEC SQL
直接写 SQL 字符串,无需前缀 需要预处理器 Python 解释器直接执行 SQL 语句 编译器统一处理 PyMySQL 自动解析和执行 PyMySQL是“无预编译”的,不需要预处理。我们直接把SQL写在字符串里传给
cursor.execute()
即可 -
预处理要求
C语言写法 Python 写法(等价实现) EXEC SQL SELECT ...;
cursor.execute("SELECT ...")
C 中语句结尾需要 ;
Python 中只需字符串 + 变量 -
Python+PyMySQL的编译过程
- SQL写入
cursor.excute
- Python解释器直接执行SQL语句
- 数据库通信、语法处理、结果接收等工作由 PyMySQL 封装的内部模块自动完成
- SQL写入
2. 数据库和主语言程序间的通信
SQL与C语言
-
数据库的DBMS负责数据存取,SQL语句的执行是否成功,其执行结果需反馈给应用程序
-
在SQL中设有一通信区SQLCA(SQL Communication Area)
- 这是一个数据结构,其中包含描述DBMS当前工作状态的若干信息
-
应用程序和用户通过SQLCA了解数据库的执行情况
- SQLCA中有一状态指示单元SQLCODE,用于存放SQL语句的执行结果,通过判断SQLCODE的值可以知道SQL语句的执行情况(0表示成功)
-
应用程序引用SQLCA,需要加以说明,格式为:
EXEC SQL INCLUDE SQLCA;
-
-
SQLCA的具体内容
- 与所执行的SQL语句有关
- 与该SQL语句的执行情况有关
MySQL与Python
-
数据库的 PyMySQL 负责数据存取,SQL 语句的执行是否成功,其执行结果需要反馈给应用程序
-
在PyMySQL中没有SQLCA,但用
try/except
完成通信机制- 在PyMySQL中,
try/except
是通信机制的核心- 我们不需要手动检查状态码
- SQL一旦执行出错,程序会自动跳转到
except
部分
- 在PyMySQL中,
-
try/except
的作用- 是Python中处理 SQL执行成功或失败 的主要方式
- 可以获取详细的异常信息,如:
- 语法错误
- 数据库连接失败
- 表不存在
- SQL执行失败等
-
语法格式
try:# 可能出错的代码块cursor.execute("SQL语句", 参数) # 可以是 INSERT、SELECT、UPDATE、DELETE 等result = cursor.fetchall() # 如果是查询可以这样获取结果# 处理查询结果(可以打印,也可以判断结果是否为空) except Exception as e:# 出现异常后的处理逻辑print("SQL执行出错,错误信息如下:")print(e) finally:# 无论对错都执行(常用于关闭连接)conn.close()
结构 用途说明 try:
放你“可能出错”的代码块(执行 SQL 的语句) except Exception as e:
捕获所有类型的 SQL 错误,并把错误信息存到变量 e
print(e)
打印错误信息(如:语法错误、表不存在等) finally:
不论是否出错,都执行的代码(如关闭数据库连接)
-
3. 数据库和主语言程序间的数据交换
SQL与C语言
-
嵌入式SQL语句通过主变量与主语言程序进行数据交换。
-
在SQL语句中使用的主语言程序变量简称为主变量(Host Variable)或宿主变量。按用途分:
- 输入变量
- 指定向数据库中插入的数据;
- 将数据库中的数据修改为指定值;
- 指定执行的操作;
- 指定
WHERE
子句或HAVING
子句中的条件;
- 输出变量
- 获取SQL语句的结果数据
- 获取SQL语句的执行状态
- 输入变量
-
主变量的使用
- 输入主变量
- 由应用程序对其赋值,SQL语句引用
- 输出主变量
- 由SQL语句赋值或设置状态信息,返回应用程序
- 一个主变量有可能既是输入主变量又是输出主变量
- 主变量可以出现在SQL语句中任何一个能够使用表达式的地方
- 先说明后使用
- 为了区别于数据库对象(表、视图、列等),在SQL语句中,主变量前要加冒号“:”作为标志。
- 输入主变量
-
主变量的说明格式
EXEC SQL BEGIN DECLARE SECTION; <主变量> EXEC SQL END DECLARE SECTION;
MySQL与Python
-
嵌入式SQL通过主变量与主语言程序进行数据交换
-
在PyMySQL中,主变量 = Python中的普通变量,在SQL语句中使用的主语言程序变量,简称主变量(Host Varaible)。主变量按用途分类:
-
输入变量
- 指定向数据库中插入的数据;
- 将数据库中的数据修改为指定值;
- 指定执行的操作;
- 指定
WHERE
子句或HAVING
子句中的条件;
示例(插入一条记录):
sno = "S01" sname = "张三" sage = 20 cursor.execute("INSERT INTO Student (Sno, Sname, Sage) VALUES (%s, %s, %s)", (sno, sname, sage))
-
输出变量
- 获取SQL语句的结果数据;
- 获取SQL语句的执行装填(Python用
try/except
实现)
示例(输出查询结果)
cursor.execute("SELECT Sname FROM Student WHERE Sno = %s",("S01,")) result = cursor.fetchone() print("学生姓名:",resultp[0])
-
-
主变量的使用
-
输入主变量
- 由应用程序对其赋值,SQL语句引用
-
输出主变量
- 由SQL语句执行后将结果写入变量,再由应用程序使用
-
同一个主变量可以同时作为输入和输出变量
-
可以出现在 SQL 中任意表达式的位置
-
先定义再使用
-
在C语言中主变量要加前缀
:
,而Python中不用加C语言嵌入式SQL Python PyMySQL 实现 EXEC SQL SELECT Sname INTO :name ...
cursor.execute("SELECT Sname WHERE ...")
:变量名
(代表主变量)使用 Python 普通变量即可,无需特殊标记
-
-
主变量的说明格式
Python中主变量“说明格式”就是变量定义
在C中:
EXEC SQL BEGIN DECLARE SECTION; char Sno[6]; int Age; EXEC SQL END DECLARE SECTION;
在Python中:
sno = "S02" age = 20
无需声明块,直接定义即可使用。
4. 面向集合和面向记录的协调
SQL与C语言
- SQL语句是面向集合的,一条SQL语句可以产生或处理多条记录;主语言是面向记录的,一组主变量一次只能存放一条记录。
- 使用主变量并不能满足SQL语句面向应用程序输出数据的要求。
- 嵌入式SQL引入游标(cursor)机制来协调面向集合和面向记录的不同处理方式。
- 游标是系统为用户开设的一个数据缓冲区里,存放SQL语句的执行结果。
- 游标包含两部分:
- 定义该游标的
SELECT
语句返回的结果集; - 指向结果集中某一行的指针。
- 定义该游标的
MySQL与Python
-
SQL语言是面向集合的,Python是面向记录的
-
SQL是面向集合的,一条SQL语句可以产生或处理 多条记录,如
SELECT * FROM Student;
会一次性返回所有学生记录(结果集)
-
Python是面向记录的,程序中的变量一次只能存放一条记录(一个元组),Python必须通过循环、游标等方式,一行一行读取数据
-
-
使用普通变量(主变量)无法满足SQL输出多个记录的需求
- 一个变量如
row = cursor.fetchone()
只能接受一行 - 要处理所有结果,就需要遍历
- 一个变量如
-
Python中的游标机制(cursor)
Python的游标对象与SQL中的概念一致,本质上:是一个接口,用来协调SQL的集合结果和Python的记录式处理
-
Python实例:协调处理集合和记录
import pymysql# 连接数据库 conn=pymysql.connct(host="localhost",user='your_username',password="your_password",database='testdb') # 执行集合式查询(返回多个记录) cursor.excute("SELECT Sno,Sname,Sage FROM Student WHERE Sage > %s",(18,)) for row in cursor.fetchall():sno,sname,sage = rowprint(f"学号:{sno},姓名:{sname},年龄:{sage}")conn.close()
不用游标的嵌入式SQL
SQL与C语言
-
如果嵌入式SQL语句的执行结果为单记录,或一次处理多个记录而不是对记录逐个处理,可以不用游标。
-
不用游标的SQL语句的种类
- 说明性语句
- 数据定义语句
- 查询结果为单记录的SELECT语句
- INSERT语句
- 非CURRENT形式的UPDATE语句
- 非CURRENT形式的DELETE语句
- 授权和回收语句
“非 CURRENT 形式的 UPDATE / DELETE 语句”
意思是这些语句不依赖游标 -
不用游标,用主变量;先说明,后使用。
【例】定义字符串型主变量
Sno
和Sname
EXEC SQL BEGIN DECLARE SECTION;CHAR Sno(6);CHAR Sname(8);…… EXEC SQL END DECLARE SECTION;
- 所有主变量在使用前需用DECLARE语句说明。
- SQL语句中变量名前要加
:
(冒号),此时变量名按C语言的大小写来解释。
【例】根据学号查询姓名和选修2号课的成绩
EXEC SQL SELECT Sname,Cno,GradeINTO :Hsname,:Hcno,:HgradeFROM Student,SCWHERE Student.Sno = :Hsno AND Cno = '2'AND Student.Sno = SC.Sno;
Hsno
为输入主变量,在执行该语句前,应先用主语言命令给Hsno
赋值INTO
子句指定将查询结果放入相应的主变量(按顺序对应)
【例】在学生选课中插入选课成绩。
EXEC SQL INSERT INTO SCVALUES (:Sno,:Cno,:GRADE);
- 在执行该语句前,应先给主变量赋值,然后执行该语句,将选课成绩插入SC表。
【例】给出学生的学号和要修改的课程号,修改学生选修记录。
EXEC SQL UPDATE SCSET Cno = :HnewcnoWHERE Sno = :Hsno AND Cno = :Holdcno;
- 主变量
Holdcno
中为修改前的课程号,Hnewcno
中为修改后的课程号。 - 非CURRENT形式的
UPDATE
语句可以操作多条记录。
【例】给出学号和课程号,删除学生选课记录。
EXEC SQL DELETE FROM SCWHERE Sno = :Hsno AND Cno = :Hcno;
- 非CURRENT形式的
DELETE
语句可以操作多个元组
MySQL与Python
-
不用游标的适用场景:如果SQL执行结果是单条记录,或不是逐条处理结果集,就可以不用游标,直接用主变量完成。
-
不用游标的SQL语句类型
- 说明性语句(Python中不涉及)
- 数据定义语句(如
CREATE TABLE
) - 查询结果为单记录的
SELECT
语句 INSERT
语句- 非
CURRENT
的UPDATE
和DELETE
- 授权和回收语句(不常用)
-
Python中主变量的使用方式:
同样是先说明再使用,但是简单得多
C语言格式:
EXEC SQL BEGIN DECLARE SECTION;CHAR Sno(6);CHAR Sname(8); EXEC SQL END DECLARE SECTION;
Python中:
Sno = "S01"; Sname = "张三";
无需
DECLARE
,变量即主变量 -
Python中游标和C语言嵌入SQL中有些不同
术语 C语言嵌入式SQL中的含义 Python / PyMySQL 中的含义 游标(cursor) 是数据库中面向集合处理的“数据指针” 是 Python 中操作数据库必须创建的对象 不用游标 指不使用 DECLARE CURSOR
来处理多条记录不是说不创建 Python 的 cursor 对象 - Python中的
cursor
本质上是一个 操作接口(我们必须用它来exexute
SQL语句),不是C语言中的“显示游标声明”
类比 MySQL术语 Python术语 SQL 游标 DECLARE C1 CURSOR FOR ...
用于处理多行结果(循环FETCH) Python 操作句柄 db.cursor()
用于执行任何 SQL 操作(必须有) - Python中的
【例】根据学号查询学生姓名和选修2号课的成绩
import pymysql # 导入 PyMySQL模块(用于操作MySQL数据库)#连接到 MySQL 数据库
db = pymysql.connect(host = 'localhost',user = 'your_username',# 填写自己的用户名password = 'your_password',# 填写自己的密码database = 'sst'
)
# 创建 cursor对象,用于执行SQL语句(这是PyMySQL必须的操作句柄)
cursor = db.cursor()# -----------------示例1:单记录查询--------
# 模拟主变量 Hsno,输入学号,查询该学生选修 C2 的成绩
hsno = "200701"# 执行查询语句(只查询一条记录,因此不用 DECLARE CURSOR 等)
cursor.execute("""SELECT Sname,Cno,GradeFROM Student,SCWHERE Student.Sno = %s AND Cno = '2' AND Student.Sno = SC.Sno""",(hsno,))
# 获取查询结果的一行,赋值给 Python 变量(相当于主变量输出)
row = cursor.fetchone()
if row != None:hsname,hcno,hgrade = rowprint(f"[查询成功] 姓名:{hsname},课程号:{hcno},成绩:{hgrade}")
else:print("[查询结果]未找到该学生选修2号课程的记录")cursor.close()
-
cursor = db.cursor()
cursor
是一个 游标对象- 作用是:用来执行 SQL语句,获取数据库返回的结果
- 可以理解为我们访问数据库的”工具句柄“
常见用法:
cursor = db.cursor() # 创建游标 cursor.execute(……) # 执行 SQL result = cursor.fetchone()# 获取一条结果 cursor.close() # 关闭游标
-
cursor.execute()
execute()
是 游标对象 cursoe的方法- 用来执行一条 SQL 语句(查询、插入、更新、删除等)
- 可以配合占位符
%s
和参数传递,避免SQL注入风险
示例
cursor.execute("SELECT * FROM Student WHERE Sno = %s",(hsno,))
说明:
- SQL中
%s
是占位符; (hsno,)
是一元元组,其中的值会安全地绑定进去,不会被当作SQL字符串拼接。
-
row = cursor.fetchone()
fetchone()
方法会从SQL查询结果中读取一行数据- 如果没有数据,会返回
None
- 结果通常一个 元组(tuple),包含这一行所有字段的值
示例:
row = cursor.fetchone() if row:name,course,grade = rowprint(name,course,grade)
-
f"……"
- 这是 Python 的 f-string(格式化字符串)
- 语法是:字符串前面加
f
,字符串中用{变量}
来嵌入变量值 - 从从 Python 3.6 开始支持,写法直观、清晰、推荐使用
示例:
name = "张三" score = 90 print(f"姓名:{name}, 成绩:{score}")
等价于
print("姓名:" + name + ", 成绩:" + str(score))
-
Python中
print()
函数的输出机制-
print()
函数语法详解print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
参数 含义 默认值 示例 *objects
要打印的多个对象 必须指定 "hello", "world"
sep
多个对象之间的分隔符 ' '
(空格)sep=','
输出hello,world
end
结尾追加的内容 '\n'
(换行)end=''
表示不换行file
输出流 sys.stdout
通常默认即可 flush
是否强制刷新缓冲区 False
用于调试 -
常用示例
-
多个对象之间自定义分隔符
print("hello", "world", sep=", ")
输出:
hello,world
-
不换行输出
print("hello", end="") print("world")
输出:
helloworld
-
结合变量和 f-string 输出更复杂内容
name = "小明" score = 95 print(f"学生 {name} 的成绩是 {score}")
输出:
学生 小明 的成绩是 95
-
-
【例】在学生选课表中插入选课成绩。
# ------------示例2:插入记录
cursor = db.cursor()
sno = "200701"
cno = "4"
grade = 88
cursor.execute("""INSERT INTO SC (Sno,Cno,Grade)VALUES (%s ,%s ,%s)""",(sno,cno,grade)
)
db.commit()
print("[插入成功] 新选课记录已添加")
db.commit()
- 提交当前事务,把之前执行的
INSERT
、UPDATE
、DELETE
等更改真正保存到数据库中。
- 提交当前事务,把之前执行的
【例】给出学生的学号和要修改的课程号,修改学生选修记录
import pymysqldb = pymysql.connect(host='localhost',port = 3306,user='your_username',passwd='your_password',database="your_database"
)cursor = db.cursor()
hsno = "200701"
holdcno = "4"
hnewcno = "5"
cursor.execute("""UPDATE sst.SCSET Cno = %s WHERE Sno = %s AND Cno = %s""",(hnewcno,hsno,holdcno))
db.commit()
print("[更新成功] 课程号已从 C2 改为 C3")
- 非CURRENT形式的
UPDATE
语句可以操作多个元组,,只要 SQL 语句的条件匹配多行。
【例】给出学号和课程,删除学生的选课记录
# 连接数据库
cursor = db.cursor()
hsno = "200701"
hcno = "5"
cursor.execute("""DELETE FROM SCWHERE Sno = %s AND Cno = %s""",(hsno,hcno))
db.commit()
print("[删除成功] 已删除选课记录")
cursor.close()
db.close()
- 非CURRENT形式的
UPDATE
语句可以操作多个元组,,只要 SQL 语句的条件匹配多行。
用游标的嵌入式SQL
SQL与C语言
- 主语言一次只能处理一条记录,当处理的结果为多条记录时,需借助游标机制,把对结果集的操作转化为对单个记录的处理。
- 必须使用游标的SQL语句
- 查询结果为多条记录的
SELECT
语句 - CURRENT形式的
UPDATE
语句 - CURRENT形式的
DELETE
语句
- 查询结果为多条记录的
- 使用游标的步骤
- 定义游标
- 打开游标
- 推动游标
- 关闭游标
1、定义游标
-
使用
DECLARE
语句 -
语句格式
EXEC SQL DECLARE <游标名> CURSOR FOR <SELECT语句>[FOR UPDATE OF <列名>];
-
功能
- 说明性语句:不会真正访问数据库,而是告诉预编译器或编译器如何处理SQL的声明性语句。
- 用于建立游标和
SELECT
语句之间的关系,并不执行SELECT
语句 FOR UPDATE OF
子句表示更新查询结果中的列
2、打开游标
-
使用
OPEN
子句 -
语句格式
EXEC SQL OPEN <游标名>;
-
功能
- 执行与游标关联的SQL查询语句,并将查询结果放入数据缓冲区。
- 此时游标处于打开装态,游标指向查询结果集中第一条记录之前的位置。
3、推动游标
-
使用
FETCH
语句 -
语句格式
EXEC SQL FETCH <游标名> INTO <主变量>[,<主变量>]……;
-
功能
-
把游标向前推进一个位置,然后按照游标的当前位置取一条记录(元组),将元组的值赋给对应的主变量。
-
每执行一次该语句,游标向前推进一个位置。
-
如果最后游标指针所指的位置为空,则
SQLCODE
返回一个状态码,表示缓冲区没有可处理的元组。SQLCODE
是嵌入式SQL中的一个状态码变量,当执行SQL语句时,系统会自动设置它的值SQLCODE值 意义 0 执行成功 +100 没有更多数据(FETCH 到底) <0 执行错误
-
4、关闭游标
-
使用
CLOSE
语句 -
语句格式
EXEC SQL CLOSE <游标名>
-
功能
- 关闭游标,释放结果集占用的缓冲区及其他资源
-
说明
- 游标被关闭后,就不再和原来的查询结果集相联系
- 被关闭的游标可以再次被打开,与新的查询结果相联系
游标使用示例
使用游标查询学生选课记录。
EXEC SQL DECLARE C1 CURSOR FOR
SELECT Sno,Cno,Grade FROM SC;
EXEC SQL OPEN C1;
while(1){EXEC SQL FETCH C1INTO :Hsno,:Hcno,:Hgrade;if (sqlca,sqlcode != 0) break;printf("sno:%s,cno:%s,grade:%d",Hsno,Hcno,Hgrade);……
};
EXEC SQL CLOSE C1;
游标的扩充
-
为进一步方便用户处理数据,现在一些关系数据库关系系统对
FETCH
语句做了扩充,允许用户向任意方向以任意步长移动游标指针。 -
SQL2提供了滚动游标(Scroll Cursor)
-
EXEC SQL DECLARE <游标名> SCROLL CURSOR FOR <SELECT 语句>[FOR UPDATE OF <列名>];
-
EXEC SQL FETCH [NEXT|PRIOR|FIRST|LAST|ABSOLUTE n|RELATIVE n]<游标名>INTO <主变量>[,<主变量>]……;
FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE n | RELATIVE n] <游标名> INTO <主变量>
:使用不同的选项控制游标的移动:NEXT
:向前移动到结果集的下一条记录。PRIOR
:向后移动到结果集的上一条记录。FIRST
:移动到结果集的第一条记录。LAST
:移动到结果集的最后一条记录。ABSOLUTE n
:移动到结果集的第n条记录。RELATIVE n
:相对当前位置移动n条记录(向前或向后)。
-
CURRENT形式的UPDATE和DELTE语句
-
CURRENT形式的更新语句格式:
EXEC SQL UPDATE <表名>SET = <表达式>WHERE CURRENT OF <游标名>
CURRENT OF <游标名>
表示当前游标所指的记录- 要求游标的定义带有
FOR UPDATE
子句
-
CURRENT形式的删除语句格式为:
EXEC SQL DELETE FROM <表名>WHERE CURRENT OF <游标名>;
- 要求使用带
FOR UPODATE
的DECALARE
语句定义游标
- 要求使用带
MySQL与Python
- 主语言一次只能处理一条记录,当处理的结果为多条记录时,需借助游标机制,把对结果集的操作转化为对单个记录的处理。
- 必须使用游标的SQL语句
- 查询结果为多条记录的
SELECT
语句 - CURRENT形式的
UPDATE
语句 - CURRENT形式的
DELETE
语句
- 查询结果为多条记录的
- 使用游标的步骤
- 定义游标
- 打开游标
- 推动游标
- 关闭游标
1、定义游标
在Python中,使用PyMySQL不需要显示声明游标,而是直接使用cursor
对象进行查询操作。游标对象会自动处理与SQL查询的关系。
在PyMySQL中,cursor
是一个非常关键的对象,它的作用是用来执行SQL查询并获取结果。可以把它理解为数据库操作的“接口”,它使得您能够执行SQL语句并从数据库获取数据。虽然它是一个“接口”,但它也具有存储结果集的功能。
- cursor的角色
在数据库编程中,游标(cursor)通常指代一个指向查询结果集的指针,用于逐条检索数据。在PyMySQL中,cursor对象充当了这个角色,允许我们执行查询、获取结果以及管理数据库连接。
- cursor的功能
- 执行SQL语句:游标对象允许我们执行SQL语句(例如
SELECT
、INSERT
、UPDATE
、DELETE
等),并返回结果。 - 存储结果集:当执行
SELECT
查询时,结果集会存储在游标对象中。游标通过fetchall()
、fetchone()
等方法来访问这些数据。 - 提供接口与数据库通信:通过
cursor
对象,Python代码与数据库之间建立了一个连接,您可以通过它传递SQL语句、获取执行状态或获取查询结果。
- cursor如何存取结果集
当执行查询时,游标会与数据库建立一个内部连接,并从数据库中检索数据。数据会存储在游标对象的内部缓冲区中。我们可以通过以下几种方法从游标中获取数据:
fetchall()
:返回查询结果中的所有记录,通常是一个列表,列表中的每个元素代表查询结果集中的一行数据。fetchone()
:返回查询结果中的下一行(如果有的话),每次调用会返回查询结果集中的一条记录。fetchmany(n)
:返回查询结果中的前n
条记录。
2、打开游标
在Python中,使用PyMySQL时没有显示的OPEN
语句。cursor.execute()
执行查询后,游标会自动打开并准备结果集供后续操作。
结果集是指执行SQL查询语句后返回的数据集合。
在Python中,使用
PyMySQL
时,当我们执行查询(SELECT
)语句后,数据库返回的结果集会存储在游标对象(cursor
)中。你可以通过游标对象的方法来访问这些数据。
fetchall()
:返回查询结果集中的所有记录。fetchone()
:返回结果集中的第一条记录。fetchmany(n)
:返回结果集中的前n条记录。
3、推动游标
在Python中,PyMySQL的游标对象支持fetchone()
、fechall()
等方法,可以逐行读取结果。
fetchone()
:获取查询结果的下一条记录。fetchall()
:获取查询结果的所有记录。
示例代码:fetchone()
import pymysql# 连接到MySQL数据库
db = pymysql.connect(host='localhost',user='root',password='password',database='pharma_sales_system'
)cursor = db.cursor()# 执行查询,获取学生信息
cursor.execute("SELECT Sno, Sname, Sdept FROM Student WHERE Sage > %s", (18,))# 使用fetchone()逐行获取结果
row = cursor.fetchone() # 获取第一行
while row:print(f"学号: {row[0]}, 姓名: {row[1]}, 专业: {row[2]}")row = cursor.fetchone() # 获取下一行cursor.close()
connection.close()
示例代码:fetchall()
在使用fetchall()
时,它会一次性获取查询结果的所有行,并返回一个包含所有行的列表,每一行是一个元组。
'''
一样先连接数据库
'''
cursor = db.cursor()# 执行查询,获取学生信息
cursor.execute("""SELECT Sno,Sname,Sdetp FROM StudentWHERE Sage > %s""",(18,))# 使用fetchall()获取所有结果
rows = cursor.fetchall()for row in rows:print(f"学号:{row[0]},姓名:{row[1]},专业:{row[2]}")curosr.close()
db.close()
4、关闭游标
在Python中,游标是一个负责数据库操作的对象。通过使用完游标后,通常我们会调用cursor.close()
来关闭游标并释放资源。
游标的使用示例
import pymysqldb = pymysql.connect(host = 'localhost',user = 'your_username',password = 'your_password',database = 'your_database'
)cursor = db.cursor()cursor.execute("""SELECT Sno ,Sname,Ssex,Sage,SdeptFROM StudentWHERE Sage > 18""")row = cursor.fetchone()
while row is not None:print(row)row = cursor.fetchone()cursor.close()
db.close()
滚动游标的扩充
滚动游标(Scroll Cursor)是SQL2标准的一项扩展,它允许开发者对游标进行更灵活的控制。与普通的游标只能向前逐条处理查询结果集不同,滚动游标允许您向前、向后或根据指定位置自由地在查询结果集中移动游标。
-
什么是滚动游标
滚动游标允许程序员控制游标的移动方向,不仅限于“下一条记录”,还可以“上一条”,或者直接跳转到结果集中的任何一条记录,甚至是从当前位置相对偏移一定数量,或者直接跳到绝对某一记录。
-
滚动游标的有点
- **灵活性:**滚动游标提供了比普通游标更多的控制,可以随时调整游标的位置,不需要依赖默认的向前查询结果。
- 性能:对于需要访问查询结果集不同部分的数据(例如随机访问或反向迭代),滚动游标比普通游标更有效。
-
滚动游标的语法
虽然PyMySQL并不直接支持滚动游标(即没有直接的
SCROLL CURSOR
语法),但我们可以通过对查询结果集进行操作,模拟滚动游标的行为。示例:模拟滚动游标
在Python中,使用
fetchall()
方法可以获取所查询结果,之后我们可以通过手动管理索引来模拟游标的“滚动”行为。import pymysql# 连接到MySQL数据库 db = pymysql.connect(host='localhost',user='root',password='password',database='pharma_sales_system' )cursor = db.cursor()# 执行查询操作 cursor.execute("SELECT Sno, Sname, Sdept FROM Student WHERE Sage > %s", (18,)) students = cursor.fetchall() # 获取所有查询结果# 模拟滚动游标 index = 0# 向前(模拟NEXT) print("向前(模拟NEXT):") while index < len(students):print(f"学号: {students[index][0]}, 姓名: {students[index][1]}, 专业: {students[index][2]}")index += 1# 向后(模拟PRIOR) print("\n向后(模拟PRIOR):") while index > 0:index -= 1print(f"学号: {students[index][0]}, 姓名: {students[index][1]}, 专业: {students[index][2]}")cursor.close() db.close()
CURRENT形式的UPDATE和DELTE语句
在Python中,我们通过cursor.execute()
来执行UPDATE
语句,而不需要CURRENT
关键字。我们可以通过查询来选择特定记录,然后更新它们。
示例:更新成绩(直接执行UPDATE
操作)(一次运行只能删除一个)
import pymysqldb = pymysql.connect(host = 'localhost',user = 'your_username',password = 'your_password',database = 'yout_database'
)cursor = db.cursor()# 假设我们要更新选修数据库课程的学生成绩
cursor.execute("""SELECT Sno,Cno,GradeFROM SCWHERE Grade < %s""",(80,))# 使用fetchone()逐条获取查询结果并更新
row = cursor.fetchone()
while row :sno = row[0]cno = row[1]grade = row[2]# 更新当前记录的成绩,假设成绩加5分new_grade = grade + 5cursor.execute("""UPDATE SCSET Grade = %sWHERE Sno = %s AND Cno = %s""",(new_grade,sno,cno))row = cursor.fetchone()db.commit()
cursor.close()
db.close()
错误:该代码一次运行,只能更改一行元组(成绩小于80)。
原因:
- 当
cursor.execute("""SELECT Sno,Cno,Grade FROM SC WHERE Grade < %s""",(80,))
之后; - 对应的数据库会建立一个虚表,然后
cursor
会指向虚表的第一行数据 cursor.execute("""UPDATE SC SET Grade = %s WHERE Sno = %s AND Cno = %s""",(new_grade,sno,cno))
之后,cursor
会被刷新,就是说,cursor
更新完对应的元组后,cursor
会指向“无结果集”状态- 那么下一行
row = cursor.fetchone()
,row
将会是None
。
解决方案:
- 使用两个游标,一个保留查询结果集,一个用作更新
- 一次性全部更新,像下面这个示例
示例:更新成绩(执行UPDATE
操作)(正确)
import pymysqldb = pymysql.connect(host = 'localhost',user = 'root',password = 'your_password',database = 'your_database'
)cursor = db.cursor()# 假设我们要更新选修数据库课程的学生成绩
cursor.execute("""SELECT Sno, Cno, GradeFROM SCWHERE Grade < %s""", (80,))# 使用fetchone()逐条获取查询结果
rows_to_update = [] # 存储要更新的数据
row = cursor.fetchone()
while row:sno = row[0]cno = row[1]grade = row[2]# 更新当前记录的成绩,假设成绩加5分new_grade = grade + 5rows_to_update.append((new_grade, sno, cno)) # 将要更新的数据保存到列表中row = cursor.fetchone()# 批量更新成绩
cursor.executemany("""UPDATE SCSET Grade = %sWHERE Sno = %s AND Cno = %s""", rows_to_update)# 提交一次事务
db.commit()cursor.close()
db.close()
-
executemany()
:executemany()
方法用于一次性执行多个SQL语句,并将一组参数传递给每个语句。它的用法是将SQL语句和一个包含多组参数的列表传递给它,执行时会将每个参数组合并执行对应的SQL语句。语法:
cursor.executemany(sql, args)
-
sql
:需要执行的 SQL 语句,通常是带有占位符(例如%s
)的查询或更新语句。 -
args
:包含多组参数的可迭代对象(例如列表、元组或生成器)。每一组参数都将被传递给 SQL 语句中的占位符。
在你代码中的使用:
在你提供的代码中,
executemany()
用来执行批量更新操作,将多个UPDATE
语句合并成一个批量执行的操作。具体来说:-
构建数据:
你先通过fetchone()
获取所有需要更新的记录,并将它们存储到一个列表rows_to_update
中。每一条数据都是一个包含(new_grade, sno, cno)
的元组,其中:new_grade
是更新后的成绩,sno
是学生的学号,cno
是课程编号。
-
执行批量更新:
python复制代码cursor.executemany("""UPDATE SCSET Grade = %sWHERE Sno = %s AND Cno = %s """, rows_to_update)
executemany()
会将rows_to_update
列表中的每一个元组传递给 SQL 语句中的占位符%s
,然后批量执行多个更新操作。假设
rows_to_update
列表中有以下内容:python复制代码rows_to_update = [(85, 101, 'CS101'),(88, 102, 'CS102'),(90, 103, 'CS103') ]
那么
executemany()
会执行以下三个UPDATE
语句:sql复制代码UPDATE SC SET Grade = 85 WHERE Sno = 101 AND Cno = 'CS101'; UPDATE SC SET Grade = 88 WHERE Sno = 102 AND Cno = 'CS102'; UPDATE SC SET Grade = 90 WHERE Sno = 103 AND Cno = 'CS103';
-
提交事务:
调用db.commit()
后,所有更新操作将一起提交到数据库中,确保数据的一致性和原子性。
-
示例:删除数据
```
连接数据库
```cursor = db.cursor()cursor.execute("""SELECT Sno,Cno FROM SCWHERE Grade < 60""")rows = cursor.fetchall()
cursor_delete = db.cursor()
for row in rows:cursor_delete.execute("DELETE FROM SC WHERE Sno = %s AND Cno = %s",(row[0],row[1]))db.commit()
cursor.close()
cursor_delete.close()
db.commit()
嵌入式SQL应用示例
SQL与C语言
-
应用实例
下面通过一个 C 语言的例子说明嵌入式 SQL 的编程框架和嵌入式 SQL 语句的使用。在这个例子中,使用游标查询并显示学生选修课的成绩,如果成绩在 85 分以上,显示成绩为“优”,在 75~84 之间,成绩为“良”,在 60~74 之间,成绩为“及格”,在 60 分以下,成绩为“不及格”。
#include <stdio.h>/* 定义变量段 */ EXEC SQL BEGIN DECLARE SECTION;CHAR uid[20];CHAR pwd[20];CHAR hname[20];CHAR hcno[6];INT hgrade;CHAR hsno[10]; EXEC SQL END DECLARE SECTION;/* 定义嵌入SQL环境 */ EXEC SQL INCLUDE SQLCA;int main() {char g[6];/* 建立与DBMS的连接 */strcpy(uid, "user");strcpy(pwd, "sql");EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;/* 输入课程号 */scanf("%s", hcno);/* 定义游标 */EXEC SQL DECLARE C1 CURSOR FORSELECT Sno, GradeFROM SCWHERE Cno = :hcno;/* 打开游标 */EXEC SQL OPEN C1;/* 逐行提取记录 */while (1) {EXEC SQL FETCH C1 INTO :hsno, :hgrade;if (sqlca.sqlcode < 0) // 错误break;if (hgrade >= 85)strcpy(g, "优");else if (hgrade >= 75)strcpy(g, "良");else if (hgrade >= 60)strcpy(g, "及格");elsestrcpy(g, "不及格");printf("Sno: %s Grade: %s\n", hsno, g);}/* 关闭游标 */EXEC SQL CLOSE C1;/* 提交事务,退出 */EXEC SQL COMMIT WORK RELEASE;return 0; }
-
依次检查某个系的学生记录,交互式更新某些学生年龄
#include <stdio.h>/* 主变量说明开始 */ 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; /* 主变量说明结束 *//* 定义SQL通信区 */ EXEC SQL INCLUDE SQLCA;int main(void) /* C语言主程序开始 */ {int count = 0;char yn; // 变量 yn 表示是否更新(yes/no)printf("Please choose department name(CS/MA/IS): ");scanf("%s", Deptname); // 为主变量 Deptname 赋值/* 连接数据库 TEST */EXEC SQL CONNECT TO TEST@localhost:54321 USER "SYSTEM"/"MANAGER";/* 定义游标 SX */EXEC SQL DECLARE SX CURSOR FORSELECT Sno, Sname, Ssex, SageFROM StudentWHERE SDept = :Deptname;/* 打开游标 SX,指向查询结果第一行 */EXEC SQL OPEN SX;/* 用循环结构逐条处理结果集中的记录 */for (;;) {/* 推进游标,将当前数据放入主变量 */EXEC SQL FETCH SX INTO :Hsno, :Hsname, :Hssex, :Hsage;if (SQLCA.SQLCODE != 0) // SQLCODE != 0 表示无数据或错误break;/* 如果是第一行,打印表头 */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);/* 嵌入式SQL更新语句 */EXEC SQL UPDATE StudentSET Sage = :NEWAGEWHERE CURRENT OF SX; // 对当前游标指向的学生进行更新}}/* 关闭游标 SX */EXEC SQL CLOSE SX;/* 提交事务,断开数据库连接 */EXEC SQL COMMIT WORK;EXEC SQL DISCONNECT TEST;return 0; // C语言主程序结束 }
Python与MySQL
-
应用实例
下面通过一个 C 语言的例子说明嵌入式 SQL 的编程框架和嵌入式 SQL 语句的使用。在这个例子中,使用游标查询并显示学生选修课的成绩,如果成绩在 85 分以上,显示成绩为“优”,在 75~84 之间,成绩为“良”,在 60~74 之间,成绩为“及格”,在 60 分以下,成绩为“不及格”。
import pymysql# 连接到数据库 db = pymysql.connect(host='localhost',user='your_username',password='your_password',database='your_database',charset='utf8mb4' )cursor = db.cursor() # 用户输入课程号 hcno = input("请输入课程号 Cno:")# 使用参数化查询,防止SQL注入 cursor.execute("""SELECT Sno,Grade FROM SCWHERE Cno = %s""",(hcno,))# 逐行提取记录 row = cursor.fetchone() while row:hsno,hgrade = row# 判断成绩if hgrade >= 85:g = '优'elif hgrade >= 75:g = '良'elif hgrade >= 60:g = '及格'else:g = '不及格'print(f"Sno:{hsno} Grade:{g}")row = cursor.fetchone() #提交事务(此处虽然是只读查询,但保留习惯) db.commit() # 关闭资源 cursor.close() db.close()
-
什么是SQL注入?
SQL注入是一种攻击方式,攻击者通过在输入中插入恶意SQL代码,是的程序原本预期执行的SQL查询变成攻击者想要执行的内容,进而获取、修改甚至删除数据库中的数据,
举个例子:
hcno = input("请输入课程号:") cursor.execute("SELECT Sno, Grade FROM SC WHERE Cno = '" + hcno + "'")
如果用户输入的是正常的课程号,如
4
,那么SQL执行的是:SELECT Sno, Grade FROM SC WHERE Cno = '4'
但如果有人输入的是:
4' OR '1' = 1
那么拼接后的SQL语句是:
SELECT Sno, Grade FROM SC WHERE Cno = '4' OR '1'='1'
这会导致:
- 查询条件恒为真
- 数据库可能返回所有学生成绩
- 攻击者绕过安全验证,甚至篡改数据
-
因此我们采用参数化查询
参数化查询不会直接把用户输入拼接到 SQL 字符串中,而是将用户输入作为参数绑定,在执行时由数据库自动处理转义和类型检查,从而 避免恶意代码被解释为 SQL 语句的一部分。
cursor.execute("SELECT Sno, Grade FROM SC WHERE Cno = %s", (hcno,))
-
-
依次检查某个系的学生记录,交互式更新某些学生年龄
import pymysql# 连接到MySQL数据库 db = pymysql.connect(host='localhost',user='your_username',password='your_password',database='your_database', # 替换为实际的数据库名称charset='utf8mb4' )cursor = db.cursor()# 用户输入专业名称 Depaname = input("请输入专业名吃称(计算机系/外语/数学):")# 执行查询,获取指定系别的学生记录 cursor.execute("""SELECT Sno,Sname,Ssex,Sage FROM StudentWHERE Sdept = %s """,(Depaname,))# 打印表头 print("\n %-10s %-20s %-10s %-10s" %("Sno","Sname","Ssex","Sage"))# 逐条处理查询结果并更新 count = 0 while True:row = cursor.fetchone()if not row:breakhsno,hsname,hssex,hsage = row# 打印当前学生信息print("%-10s %-20s %-10s %-10s" % (hsno,hsname,hssex,hsage))# 询问是否更新当前学生年龄yn = input("是否更新学生年龄,y/n (y/n)?").strip().lower()if yn == 'y':new_age = int(input("输入新的年龄:"))# 执行更新,更新当前学生的年龄cursor_update = db.cursor()cursor_update.execute("""UPDATE StudentSET Sage = %sWHERE Sno = %s""",(new_age,hsno))count += 1# 提交事务(保存所有更改) db.commit()# 关闭游标和数据库连接 cursor.close() db.close()print(f" {count} students.")
动态SQL
SQL与C语言
-
静态SQL
- 数据库对象、查询条件以及所做的操作,在预编译时都是确定的。
- 语句主变量的个数与数据类型在预编译时也是确定的。
- 用户可以在程序运行过程中根据实际需要输入
WHERE
子句或HAVING
子句中某些变量的值。 - 只是主变量的值可以在程序运行过程中动态输入。
- 静态SQL语句提供的编程灵活性在许多情况仍显的不足,不能编写更为通用的程序。
-
动态SQL
- 在程序运行期间临时组装SQL语句。
-
动态SQL的应用范围
- 在预编译时下列信息不能确定时
- SQL语句正文
- 主变量个数
- 主变量的数据类型
- SQL语句中引用的数据库对象(列、索引、基本表、视图等)
- 在预编译时下列信息不能确定时
-
动态SQL的形式
- 语句可变
- 临时构造完整的SQL语句
- 条件可变
WHERE
子句中的条件HAVING
短语中条件
- 数据库对象、查询条件均可变
SELECT
子句的列明FROM
子句的表明或视图名WHERE
子句中的条件HAVING
短语中的条件
- 语句可变
-
动态SQL语句的参数化
- 使用主变量
- 动态参数
- SQL语句中的可变元素;
- 使用参数符号(?)表示该位置的数据在运行时设定
- 输入不是在编译时完成绑定,而是通过
PREPARE
语句准备主变量和执行语句EXECUTE
绑定数据或主变量来完成。
-
动态SQL的执行方式
-
即输入后直接执行
EXEC SQL EXECUTE IMMEDTATE <主变量1>;
-
经过预处理后多次执行
预处理语句格式:
EXEC SQL PREPARE <语句名> FROM <主变量1>;
执行语句格式:
EXEC SQL EXECUTE <语句名> [USING <主变量2>];
-
主变量1中存放可执行的SQL语句
-
主变量2给出与语句名关联的SQL语句的参数
-
【直接执行】
String dstr = "DELETE FROM SC WHERE Sno = 'S01';";
const char *stms = "CREATE TABEL test(a int);";
EXEC SQL EXECUTE IMMEDIATE :dstr;
EXEC SQL EXECUTE IMMEDIATE :stms;
【预处理执行】
strcpy(dstr,"UPDATE SC SET Grade = :g WHERE Cno = '5';");
EXEC SQL PREPARE S1 FROM :dstr;
EXEC SQL EXECUTE S1 USING :HGrade;
【动态参数】
EXEC SQL BEGIN DECLARE SECTION;const char* stmt = "INSERT INTO test VALUES(?);";
EXEC SQL END DECLARE SECTION;
……
EXEC SQL PREPARE mystmt FROM :stmt;/*准备语句*/
EXEC SQL EXCUTE mystmt USING 100;/*执行语句,设定INSERT语句插入值100*/
EXEC SQL EXCUTE mystmt USING 200;/*执行语句,设定INSERT语句插入值200*/
MySQL与Python
概念描述差不多,执行方式有差别
Python实现动态SQL的方式
-
直接拼接并执行SQL字符串(使用占位符 + 绑定参数)
sql = "UPDATE Student SET Sage = %s WHERE SDept = %s" data = (22, 'CS') cursor.execute(sql, data)
Python中静态SQL示例
cursor.execute("""SELECT * FROM Student WHERE Sdept = %s AND Sage > %s""",("CS",20)
)
Python中动态SQL示例
base_sql = "SELECT * FROM Student"
conditions = []
dept = input ("请输入专业:")
if dept:conditions.append(f"Sdept = '{dept}'")min_age = input("请输入最低年龄:")
if min_age:conditions.append(f"Sage >= {min_age}")if conditions:base_sql = base_sql + " WHERE " + "AND".join(conditions)
-
join()
的作用是:把列表中多个字符串,用指定的连接符拼成一个新字符串。假设我们有这个列表:
conditions = ["Sdept = 'CS'", "Sage >= 20"]
如果我们直接执行:
" AND ".join(conditions)
结果是:
"Sdept = 'CS' AND Sage >= 20"
嵌入式SQL小结
- 在嵌入式SQL中,SQL语句与逐语句分工非常明确
- SQL语句直接与数据库打交道;
- 主语言语句,控制程序流程,对SQL语句的执行结果做进一步加工处理。
- SQL语句用主变量从主语言中接受执行参数,操纵数据库。
- SQL语句的执行状态由DBMS送至SQLCA中,主语言程序从SQLCA中读取状态信息,据此决定下一步操作。
- 如果SQL语句从数据库中成功检索出数据,则通过主变量传给主语言进行下一步处理。
- SQL语言和主语言的不同数据处理方式通过游标来协调。
第四章小结
-
SQL的特点
- 综合统一
- 高度非过程化
- 面向集合的操作方式
- 同一种语法结构提供两种使用方式(这是指 SQL 中的某些语法结构,既可以用在交互式环境中(直接输入运行),也可以嵌入到程序语言中(嵌入式/API调用))
- 语言简便,易学易用
-
交互式SQL的功能
- 数据定义(
CREATE
,DROP
,ALTER
) - 数据查询(
SELECT
) - 数据更新(
INSERT
,UPDATE
,DELETE
) - 数据控制(
GRANT
,REVOKE
)
- 数据定义(
-
数据查询
- 对表的选取(
FROM
) - 对列的选取(
SELECT
)- 目标表达式、可更改列标题
- 对行的选取(
WHERE
)- 消除重复行,
WHERE
子句等条件表达式
- 消除重复行,
- 排序(
ORDER BY
) - 聚集函数
MIN
、MAX
、AVG
、SUM
、COUNT
……
- 分组
GROUP BY(GROUP BY …… HAVING)
- 对表的选取(
-
WHERE
子句的条件表达式-
比较操作符
=
、>
、<
、>=
、<=
、<>
-
确定范围
BETWEEN…… AND……
-
集合查找
IN
-
字符串匹配(
LIKE
、匹配符:_
、%
) -
空值运算
IS NULL
-
多重条件组合
逻辑表达式或逻辑运算符
-
-
单表查询
-
多表连接查询
- 条件连接
- 等值连接
- 自然连接
- 外连接
- 复合条件连接
- 嵌套查询(子查询)
- 不相关子查询
- 相关子查询
-
集合查询
-
数据更新
- 插入数据
- 插入单条数据
- 插入多条数据
- 修改数据
- 更新单表数据
- 带子查询的数据修改
- 删除数据
- 删除单表数据
- 带子查询的数据删除
- 插入数据
-
视图
- 视图的作用
- 创建视图
- 使用视图
- 查询
- 更新(有条件的)
- 视图查询的实现
- 实体化
- 视图消解
-
嵌入式SQL
- 与主语言的通信方式
- SQL通信区(SQLCA)
- 主变量
- 游标
- 静态SQL
- 不用游标
- 使用游标
- 动态SQL
- 与主语言的通信方式