嵌入式SQL语言之动态SQL
Posted 计算机小白的爬坑之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式SQL语言之动态SQL相关的知识,希望对你有一定的参考价值。
嵌入式SQL语言之动态SQL
一、动态SQL的概念和作用
静态SQL特点
SQL语句在程序中已经按要求写好,只需要把一些参数通过变量(高级语言程序语句中不带冒号)传送给嵌入式SQL语句即可(嵌入式SQL语句中带冒号)。
动态SQL特点
SQL语句可以在程序中动态构造,形成一个字符串,如上例sqltext,然后再交给DBMS执行,交给DBMS执行时仍旧可以传递变量。
二、SQL语句的动态构造-示例1
程序构造
#include <stdio.h>
#include "prompt.h”
char Vcname[];
char Vcity[];
double range_from, range_to;
int Cname_chose, City_chose, Discnt_chose;
Cname_chose = 0; City_chose = 0; Discnt_chose = 0;
int sql_sign = 0;
char continue_sign[];
// 程序变量声明
// 定义
exec sql include sqlca;
exec sql begin declare section;
char user_name[20],user_pwd[20];
char sqltext[]="delete from customers where ";
exec sql end declare section;
int main()(
exec sql whenever sqlerror goto report_error; // SQL错误捕获语句
strcpy(user_name, "poneilsql");
strcpy(user_pwd, "XXXX");
exec sql connect :user_name identified
by :user_pwd; // SQL Connect
while(1)
memset(Vcname, '\\0’,20);
memset(Vcity,'\\0’,20); // 初始化
if(GetCname(Vcname))
Cname_chose =1; // 获取Cname值
if (GetCity(Vcity))
City_chose =1; // 获取City值
if (GetDiscntRange(&range_from, &range_to))
Discnt_chose=1; // 获取Discnt区间值
if (Cname_chose)
// 如果选择了Cname,构造sqltext
sql_sign = 1;
strcat(sqltoxt, "Cname = \\'");
strcat(sqItext, Vcname);
strcat(sqltext, "\\'");
if (City_chose)
// 如果选择了City,构造sqltext
sql_sign =1;
if(Cname_chose)
strcat(sqltext, " and City =\\'");
else
strcat(sqltext, "City =\\'");
strcat(sqltext, Vcity);
strcat(sqltext, "\\'");
if (Discnt_chose)
// 数值型属性条件构造
// 如果选择了Discnt区间值,构造sqltext
sql_sign =1;
if(Cname_chose=0 and City_chose = 0)
strcat(sqltext, " discnt >");
else
strcat(sqltext, " and (discnt >");
strcat(sqltext, dtoa(range_from));
strcat(sqltext, " and discnt<");
strcat(sqltext, dtoa(range_to));
strcat(sqltext, ")");
if(sql_sign)
exec sql execute immediate :sqltext; //动态SQL语句执行
exec sql commit work;
scanf("continue (y/n)%1s",continue_sign)
if(continue_sign ="n")
exec sql commit release;
returen 0;
// while 结束
report_error: // SQL Rollback Work and Disconnect
print_dberror();
exec sql rollback release;
return 1;
// main结束
三、动态SQL语句的执行方式
概述
动态SQL的两种执行方式
- 立即执行语句:运行时编译并执行
EXEC SQLEXECUTE IMMEDIATE:host-variable;
- Prepare-Execute-Using语句:PREPARE语句先编译,编译后的SQL语句允许动态参数,EXECUTE语句执行,用USING语句将动态参数值传送给编译好的SQL语句
EXECSQL PREPAREsql_temp FROM :host-variable;
EXEC SQL EXECUTEsql_temp USING :cond-variable
四、数据字典与SQLDA
1、概述
数据字典(Data dictionary),又称为系统目录(System Catalogs)。是系统维护的一些表或视图的集合,这些表或视图存储了数据库中各类对象的定义信息,这些对象包括用Create语句定义的表、列、索引、视图、权限、约束等,这些信息又称数据库的元数据–关于数据的数据。
不同DBMS术语不一样:数据字典(Data Dictionary(Oracle))、目录表(DB2UDB)、系统目录(INFORMIX)、系统视图(X/Open)
不同DBMS中系统目录存储方式可能是不同的,但会有一些信息对DBA公开。这些公开的信息,DBA可以使用一些特殊的SQL命令来检索。
数据字典的内容构成
数据字典通常存储的是数据库和表的元数据,即模式本身的信息:
- 与关系相关的信息
关系名字;每一个关系的属性名及其类型;视图的名字及其定义;完整性约束 - 用户与账户信息,包括密码
- 统计与描述性数据:如每个关系中元组的数目
- 物理文件组织信息:
关系是如何存储的(顺序/无序/散列等);关系的物理位置 - 索引相关的信息
数据字典的结构
- 存储在磁盘上的关系
- 专为内存高效访问设计的特定的数据结构
2、X/Open标准的系统目录
X/Open标准中有一个目录表Info_Schem.Tables;该表中的一行是一个已经定义的表的有关信息。
模式是指某一用户所设计和使用的表、索引及其他与数据库有关的对象的集合,因此表的完整名应是:模式名.表名。这样做可允许不同用户使用相同的表名,而不混淆。
一般而言,一个用户有一个模式。可以使用Create Schema语句来创建模式(用法略,参见相关文献),在Create Table等语句可以使用所定义的模式名称。
3、Oracle的数据字典
Oracle数据字典由视图组成,分为三种不同形式,由不同的前缀标识
- USER_ :用户视图,用户所拥有的对象,在用户模式中
- ALL_:扩展的用户视图,用户可访问的对象
- DBA_ :DBA视图(所有用户都可访问的DBA对象的子集)
Oracle数据字典中定义了三个视图USER_Tables, ALL_Tables,和DBA_Tables。供DBA和用户使用数据字典中关于表的信息
Oracle数据字典中还定义了其他视图
- TABLE_PRIVILEDGE(或ALL_TAB_GRANTS)
- COLUMN_PRIVILEDGE(或ALL_COL_GRANTS) 可访问表的权限,列的权限
- CONSTRAINT_DEFS(或ALL_CONSTRAINTS) 可访问表的各种约束
- 还有其他视图…
可以使用下述命令获取Oracle定义的所有视图信息
Select view_name from all_views where owner = 'SYS' andview_name like ‘ALL_%’ or view_name like ‘USER_%';
如果用户使用Oracle,可使用其提供的SQL*PLUS进行交互式访问
五、ODBC与JDBC
1、ODBC
ODBC是一种标准,不同语言的应用程序与不同数据库服务器之间通讯的标准。
- 一组API(应用程序接口),支持应用程序与数据库服务器的交互
- 应用程序通过调用ODBC API,实现
√ 与数据服务器的连接
√ 向数据库服务器发送SQL命令
√一条一条的提取数据库检索结果中的元组传递给应用程序的变量 - 具体的DBMS提供一套驱动程序,即Driver库函数,供ODBC调用,以便实现数据库与应用程序的连接。
- ODBC可以配合很多高级语言来使用,如C,C++,C#, Visual Basic, Power-Builder等等;
应用程序通过ODBC连接一个数据库服务器
- ODBC应用前,需要确认具体DBMS Driver被安装到ODBC环境中
- 当应用程序调用ODBC API时,ODBC API会调用具体DBMS Driver库函数,DBMS Driver库函数则与数据库服务器通讯,执行相应的请求动作并返回检索结果
- ODBC应用程序首先要分配一个SQL环境,再产生一个数据库连接句柄
- 应用程序使用SQLConnect(),打开一个数据库连接SQL Connect()的具体参数:
connection handle,连接句柄
the server,要连接的数据库服务器
the user identifier,用户
password,密码
SQL_NTS类型说明前面的参数是空终止的字符串
int ODBCexample()
RETCODE error; //返回状态码
HENV env;//环境变量
HDBC conn;//连接句柄
SQLAllocEnv(&env);
SQLAllocConnect(env,&conn);//分配数据库连接环境
SQLConnect(conn, "aura.bell-labs.com", SQL_NTS,"avi",SQL_NTS, avipasswd", SQL_NTS);
//打开一个数据库连接
.... Do actual work ...
//与数据库通讯
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
//断开连接与释放环境
- 应用程序使用SQLExecDirect()向数据库发送SQL命令;
- 使用SQLFetch()获取产生的结果元组;
- 使用SQLBindCol()绑定C语言变量与结果中的属性
当获取一个元组时,属性值会自动地传送到相应的C语言变量中
2、JDBC
JDBC是一组Java版的应用程序接口API,提供了Java应用程序与数据库服务器的连接和通讯能力。
java.sql.DriverManager——处理驱动的调入并且对产生新数据库连接提供支持
Java.sqI.Driver——通过驱动进行数据库访问,连接到数据库的应用程序必须具备该数据库的特定驱动。
java.sql.Connection——代表对特定数据库的连接。
Try .…. Catch ….——异常捕获及其处理
java.sql.Statement——对特定的数据库执行SQL语句
java.sql.PreparedStatement——用于执行预编译的SQL语句
java.sql.CallableStatement——用于执行对数据库内嵌过程的调用。
java.sql.ResultSet——从当前执行的SQL语句中返回结果数据。
概念性的基本过程
打开一个连接;创建“Statement”对象,并设置查询语句;使用Statement对象执行查询,发送查询给数据库服务器和返回结果给应用程序﹔处理错误的例外机制
具体实施过程
- 传递一个Driver给DriverManager,加载数据库驱动。
Class.forName() - 通过URL得到一个Connection对象,建立数据库连接
DriverManager.getConnection(sDBUrIl)
DriverManager.getConnection(sDBUrl,sDBUserlD,sDBPassword) - 接着创建一个Statement对象(PreparedStatement或callablestatement),用来查询或者修改数据库。
Statement stmt=con.createStatement() - 查询返回一个ResultSet。
ResultSet rs=stmt.executeQuery(sSQL)
示例
public static void JDBCexample(String dbid, String userid, String passwd) try//错误捕获
Class.forName("oracle.jdbc.driver.OracleDriver");
connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@db.yale.edu:1521:univdb", userid, passwd);
//加载数据库驱动,建立数据库连接
Statement stmt = conn.createStatement();//创建一个语句对象
... Do Actual Work ....
//进行SQL语句的执行与处理工作
stmt.close();
conn.close();
//关闭语句对象,关闭连接
catch (SQLException sqle)
System.out.println("SQLException : " + sqle);
Update to database
try stmt.executeUpdate( "insert into instructor values
(77987', 'Kim', 'Physics',98000)");
//插入一条记录
catch (SQLException sqle)
System.out.printIn("Could not insert tuple. " +sqle);
执行查询并获取和打印结果
ResultSet rset = stmt.executeQuery( "select dept_name, avg(salary)"+"“from instructor group by dept_name");
while (rset.next())
System.out.println(rset.getString("dept_name")+ " "+rset.getFloat(2));
//执行一条SQL语句。获取下一条记录。提取“dept_name"属性值,提取第2列即“平均工资”列的值
完整代码:
public static void JDBCexample(String dbid, String userid, String passwd)
try
Class.forName ("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection( "jdbc:oracle:thin: @db.yale.edu:1521:univdb", userid, passwd);
Statement stmt =conn.createStatement();
try
stmt.executeUpdate( "insert into instructor values (77987', 'Kim', 'Physics',98000)");
catch (SQLException sqle)
System.out.println("could not insert tuple." +sqle);
ResultSet rset = stmt.executeQuery( "select dept_name, avg(salary)"+ from instructor group by dept_name");
while ( rset.next())
System.out.printIn(rset.getString("dept_name")+ " "+rset.getFloat(2));
stmt.close();
conn.close();
catch (SQLException sqle)
System.out.printIn("sQLException : " +sqle);
3、嵌入式SQL的思维模式
4、ODBC的思维模式
5、JDBC的思维模式
6、基于ODBC / JDBC的数据库访问
以上是关于嵌入式SQL语言之动态SQL的主要内容,如果未能解决你的问题,请参考以下文章