嵌入式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的两种执行方式

  1. 立即执行语句:运行时编译并执行
    EXEC SQLEXECUTE IMMEDIATE:host-variable;
  2. 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命令来检索。

数据字典的内容构成
数据字典通常存储的是数据库和表的元数据,即模式本身的信息:

  1. 与关系相关的信息
    关系名字;每一个关系的属性名及其类型;视图的名字及其定义;完整性约束
  2. 用户与账户信息,包括密码
  3. 统计与描述性数据:如每个关系中元组的数目
  4. 物理文件组织信息:
    关系是如何存储的(顺序/无序/散列等);关系的物理位置
  5. 索引相关的信息

数据字典的结构

  1. 存储在磁盘上的关系
  2. 专为内存高效访问设计的特定的数据结构

2、X/Open标准的系统目录

X/Open标准中有一个目录表Info_Schem.Tables;该表中的一行是一个已经定义的表的有关信息。

模式是指某一用户所设计和使用的表、索引及其他与数据库有关的对象的集合,因此表的完整名应是:模式名.表名。这样做可允许不同用户使用相同的表名,而不混淆。

一般而言,一个用户有一个模式。可以使用Create Schema语句来创建模式(用法略,参见相关文献),在Create Table等语句可以使用所定义的模式名称。

3、Oracle的数据字典

Oracle数据字典视图组成,分为三种不同形式,由不同的前缀标识

  1. USER_ :用户视图,用户所拥有的对象,在用户模式中
  2. ALL_:扩展的用户视图,用户可访问的对象
  3. DBA_ :DBA视图(所有用户都可访问的DBA对象的子集)

Oracle数据字典中定义了三个视图USER_Tables, ALL_Tables,和DBA_Tables。供DBA和用户使用数据字典中关于表的信息

Oracle数据字典中还定义了其他视图

  1. TABLE_PRIVILEDGE(或ALL_TAB_GRANTS)
  2. COLUMN_PRIVILEDGE(或ALL_COL_GRANTS) 可访问表的权限,列的权限
  3. CONSTRAINT_DEFS(或ALL_CONSTRAINTS) 可访问表的各种约束
  4. 还有其他视图…

可以使用下述命令获取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是一种标准,不同语言的应用程序与不同数据库服务器之间通讯的标准。

  1. 一组API(应用程序接口),支持应用程序与数据库服务器的交互
  2. 应用程序通过调用ODBC API,实现
    √ 与数据服务器的连接
    √ 向数据库服务器发送SQL命令
    √一条一条的提取数据库检索结果中的元组传递给应用程序的变量
  3. 具体的DBMS提供一套驱动程序,即Driver库函数,供ODBC调用,以便实现数据库与应用程序的连接。
  4. ODBC可以配合很多高级语言来使用,如C,C++,C#, Visual Basic, Power-Builder等等;

应用程序通过ODBC连接一个数据库服务器

  1. ODBC应用前,需要确认具体DBMS Driver被安装到ODBC环境中
  2. 当应用程序调用ODBC API时,ODBC API会调用具体DBMS Driver库函数,DBMS Driver库函数则与数据库服务器通讯,执行相应的请求动作并返回检索结果
  3. ODBC应用程序首先要分配一个SQL环境,再产生一个数据库连接句柄
  4. 应用程序使用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);
	//断开连接与释放环境

  1. 应用程序使用SQLExecDirect()向数据库发送SQL命令;
  2. 使用SQLFetch()获取产生的结果元组;
  3. 使用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对象执行查询,发送查询给数据库服务器和返回结果给应用程序﹔处理错误的例外机制

具体实施过程

  1. 传递一个Driver给DriverManager,加载数据库驱动。
    Class.forName()
  2. 通过URL得到一个Connection对象,建立数据库连接
    DriverManager.getConnection(sDBUrIl)
    DriverManager.getConnection(sDBUrl,sDBUserlD,sDBPassword)
  3. 接着创建一个Statement对象(PreparedStatement或callablestatement),用来查询或者修改数据库。
    Statement stmt=con.createStatement()
  4. 查询返回一个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的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式SQL语言之动态SQL

数据库系统概念:基础的SQL

数据库系统概念笔记——第五章:高级SQL

动态SQL是什么??什么是静态SQL,动态SQL的动态体现在哪里???

嵌入式SQL语言

嵌入式SQL语言