有点累啊 整理笔记!!!
SQL
构化查询语言(Structured Query Language)简称SQL,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
1986年10 月由美国国家标准局(ANSI)通过的数据库语言美国标准,接着,国际标准化组织(ISO)颁布了SQL正式国际标准。
Pro*C/C++
在C/C++程序中嵌入SQL语句操作数据库,得到的应用程序叫做Proc*C/C++程序!优点是高效!
嵌入式SQL
能在其他编程语言中混合使用的SQL语句,叫做嵌入式SQL语句!但是各厂商对嵌入式SQL的具体实现不一样!只是接口一样,但是具体的混合语法不一样,各厂商有自己的预编译工具!
SQL86(1986年发布)中定义了对于COBOL, FORTRAN, PI/L等语言的嵌入式SQL的规范。在SQL89(1989年发布)规范中,定义了对于C语言的嵌入式SQL的规范。
宿主语言 | Pro程序 |
---|---|
C/C++ | Pro*C/C++ |
FORTRAN | Pro*FORTRAN |
PASCAL | Pro*PASCAL |
COBOL | Pro*COBOL |
PL/I | Pro*PL/I |
Ada | Pro*Ada |
1. Include 头文件 (c/c++ and pro*c/c++)
2. 定义变量
3. 定义函数
4. main
4.1 连结数据库: connect
4.2 SQL 操作语句: EXEC SQL …….;
4.3 exception handler
4.4 断开连结:
4.5 EXEC SQL COMMIT / ROLLBACK WORK release
#include
#include
#include
#include "sqlca.h"
EXEC SQL BEGIN DECLARE SECTION;
char username[32];
char password[32];
char dname[25];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca;
void sqlerror();
main()
{
EXEC SQL WHENEVER SQLERROR DO sqlerror();
strcpy(username,“scott");
strcpy(password, “*****");
EXEC SQL CONNECT:username IDENTIFIED BY:password;
EXEC SQL select dname from dept where id=10;
printf(“dname:%s \n”, dname);
}
void sqlerror()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("\n---- oracle error detected:\n");
printf("%.70s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);
}
Pro*C/C++应用程序的开发多了一个预编译的过程:pc转换成c或者cpp文件
proc iname=filename oname=outname [OptionName1=value1]…[OptionNameN=valueN]
(C++)或者直接proc xxx.pc
选项 | 说明 |
---|---|
INAME | path and filename (name of the input file) 1.pc |
ONAME | path and filename (name of the output file) 1.c 1.cc |
INCLUDE | path (头文件所在路径)–INCLUDE 路径名 或 INCLUDE =(路径名1,路径名2) |
PARSE | FULL 、 PARTIA 、 NONE (default FULL for C, Others for C++) |
CODE | ANSI_C 、 CPP (default ansi_c) |
USERID | username/password(同时包含用户名和密码) |
默认预编译得到的是C文件,使用下列选项得到C++文件
parse=none 告诉proc编译器 按照c++规范解析 dm02_hello.pc
code=cpp 告诉proc编译器 按照c++规范 生产文件
proc dm02_hello.pc parse=none code=cpp oname=dm02_hello.cc
#include
#include
#include
#include "sqlca.h"
//定义宿主变量(SQL变量)
//C语言可以直接使用
//嵌入式SQL语句里面使用的话需要加上EXEC SQL前缀
EXEC SQL BEGIN DECLARE SECTION;
char * serverid = "scott/lzj123529";
EXEC SQL END DECLARE SECTION;
int main()
{
printf("HelloWorld\n");
return 0;
}
#include
#include
#include
#include
#include "sqlca.h"
using namespace std;
EXEC SQL BEGIN DECLARE SECTION;
char * serverid = "scott/lzj123529";
EXEC SQL END DECLARE SECTION;
int main()
{
cout<<"HelloWorld\n";
return 0;
}
用到的嵌入式SQL语句:
EXEC SQL CONNECT { :user IDENTIFIED BY :oldpswd | :usr_psw }
[[ AT { dbname | :host_variable }] USING :connect_string ]
[ {ALTER AUTHORIZATION :newpswd | IN { SYSDBA | SYSOPER } MODE} ] ;
连接之前开始lsnrctl以及启动数据库服务
方法1
EXEC SQL CONNECT :usr_pwd;
方法2
EXEC SQL CONNECT :username IDENTIFIED BY :password ;
方法3
通过db_name连接没有限定名字的数据库–可以修改数据库的名字–at选项 */
EXEC SQL CONNECT :username IDENTIFIED BY :password AT :db_name USING :db_string;
/* declare needed host variables */
char username[10] = "scott";
char password[10] = "tiger";
char db_string[20] = "NYNON";
/* give the database connection a unique name */
EXEC SQL DECLARE DB_NAME DATABASE;
/* connect to the nondefault database */
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT DB_NAME USING :db_string;
1.代码里写死了用户名和密码
#include
#include
#include
#include "sqlca.h"
//定义宿主变量(SQL变量)
//C语言可以直接使用
//嵌入式SQL语句里面使用的话需要加上EXEC SQL前缀
EXEC SQL BEGIN DECLARE SECTION;
char * serverid = "scott/lzj123529";
EXEC SQL END DECLARE SECTION;
int main()
{
int ret = 0;
printf("HelloWorld\n");
EXEC SQL connect:serverid;
if(sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode ;
printf("ret :%d\n",ret);
return ret;
}
printf("connect OK!\n");
EXEC SQL COMMIT RELEASE;//提交事务并且断开
return 0;
}
2.交互式的连接数据库
EXEC SQL BEGIN DECLARE SECTION;
char user[32];
char passwd[32];
char sid[32];
EXEC SQL END DECLARE SECTION;
int main()
{
int ret = 0;
printf("user:");
scanf("%s",user);
printf("passwd:");
scanf("%s",passwd);
printf("sid:");
scanf("%s",sid);
EXEC SQL CONNECT:user IDENTIFIED BY:passwd USING:sid;
if(sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode ;
printf("ret :%d\n",ret);
return ret;
}
printf("connect OK!\n");
EXEC SQL COMMIT RELEASE;//提交事务并且断开
return 0;
}
3.连接多个数据库
3.1 通过宿主变量指定连接名字
//演示通过程序连接多个数据库
EXEC SQL BEGIN DECLARE SECTION;
char *usrname = "scott";
char *passwd = "tiger";
char *link1 = "link1"; //通过宿主变量指定连接名字
char *serverid = "orcl";
char *usrname2 = "scott";
char *passwd2 = "tiger";
char *link2 = "link2";
char *serverid2 = "orcl";
EXEC SQL END DECLARE SECTION;
int main()
{
int ret = 0;
//第一个用户连接数据库
EXEC SQL CONNECT:usrname IDENTIFIED BY:passwd AT:link1 USING:serverid ;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第一个用户连接数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第一个用户连接数据库 成功connect ok...\n");
}
//第二个用户连接数据库
EXEC SQL CONNECT:usrname2 IDENTIFIED BY:passwd2 AT:link2 USING:serverid2 ;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第二个用户连接数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第二个用户连接数据库 成功connect ok...\n");
}
//断开连接
EXEC SQL AT:link1 COMMIT RELEASE;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第1个用户断开数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第1个用户断开数据库 成功 RELEASE ok...\n");
}
EXEC SQL AT:link2 COMMIT RELEASE;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第二个用户断开数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第二个用户断开数据库 成功 RELEASE ok...\n");
}
return ret ;
}
3.2 通过系统分配方式指定连接名字
EXEC SQL BEGIN DECLARE SECTION;
char *usrname = "myscott";
char *passwd = "22";
//char *link1 = "link1";
char *serverid = "orcl";
char *usrname2 = "myscott";
char *passwd2 = "22";
//char *link2 = "link2";
char *serverid2 = "orcl";
EXEC SQL END DECLARE SECTION;
int main()
{
int ret = 0;
//使用oracle声明连接 EXEC SQL DECLARE link1 DATABASE;
EXEC SQL DECLARE link1 DATABASE;
EXEC SQL DECLARE link2 DATABASE;
//第一个用户连接数据库
EXEC SQL CONNECT:usrname IDENTIFIED BY:passwd AT link1 USING:serverid ;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第一个用户连接数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第一个用户连接数据库 成功connect ok...\n");
}
//第二个用户连接数据库
EXEC SQL CONNECT:usrname2 IDENTIFIED BY:passwd2 AT link2 USING:serverid2 ;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第二个用户连接数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第二个用户连接数据库 成功connect ok...\n");
}
//断开连接
EXEC SQL AT link1 COMMIT RELEASE;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第1个用户断开数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第1个用户断开数据库 成功 RELEASE ok...\n");
}
EXEC SQL AT link2 COMMIT RELEASE;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode;
printf("第2个用户断开数据库 失败sqlca.sqlcode: err:%d \n", sqlca.sqlcode);
return ret;
}
else
{
printf("第2个用户断开数据库 成功 RELEASE ok...\n");
}
return ret ;
}
C 的数据类型不同于ORACLE的数据类型,在数据传递时有一个数据类型转换的过程。
在Proc*C/C++程序中,能通是被C和SQL语句使用的变量!位于
EXEC SQL BEGIN DECLARE SECTION;
... ...
EXEC SQL END DECLARE SECTION;
之内!!
主要类型:
程序中形式 | 说明 |
---|---|
char | 单字符 |
char[n] | N个定长字符数组 |
int | 整数 |
Short | 短整数 |
long | 长整数 |
float | 单精度浮点数 |
double | 双精度浮点数 |
VARCHAR[n] | 变长字符串 |
使用场景:
1.输入 — 将应用程序的数据传递到数据库中。
nt salary, emp_number;
cin>>salary; cin>>emp_number;
EXEC SQL update emp set sal=:salary where empno= :emp_number;
2.输出 — 将数据库的数据传递到应用程序中。
float v_salary;
char v_job;
EXEC SQL select sal,job INTO :v_salary, :v_job from emp where empno = 7788;
cout<
3.申明语法与普通C变量一致,但在CODE=CPP或 MODE=ANSI时变量必须放在申明区.
4.可使用pointer 作为宿主变量,使用前分配空间。
5.在DDL语句中不能用宿主变量。错误例子:
char table_name[30];
cin>>table_name;
EXEC SQL DROP TABLE :table_name;
6.预编译选项 CHAR_MAP
CHAR_MAP=CHARZ (默认设置): ‘\0’结尾,定长,空格补齐。
CHAR_MAP=CHARF | VARCHAR2:定长,空格补齐。
CHAR_MAP=STRING: ‘\0’结尾,变长。
7.当‘\0’结尾,宿主变量长度要大于实际数据长度。
8.VARCHAR
* 变长, 不是‘\0’结尾。
* 结构体类型
Struct{
unsigned short len;
unsigned char arr[ ]
}variable_name;
1.内部类型
就是在Sql*Plus使用到的数据类型!
Oracle数据就是Oracle数据库内部使用的数据类型:
类型 | 说明 |
---|---|
VARCHAR2 | 变长字符串,最大4000字节 |
CHAR | 定长字符串,最大2000字节 |
NUMBER(p,s) | 数字类型,p精度,s标度 |
DATE | 日期时间数据,7字节 |
RAW | 变长二进制数据,最大2000字节 |
LONG | 大批量数据,最大2G字节 |
LONG RAW | 大二进制数据,最大2G字节 |
CLOB | 大批量字符数据,最大4G |
BLOB | 大批量二进制数据,最大4G |
BFILE | OS文件数据 |
NCHAR,NVARCHAR2,NCLOB | 本地字符集数据 |
ROWID | 伪列——表行物理地址 |
数据库中的表和伪列使用这些数据类型
2.外部类型
Oracle外部数据类型是宿主程序所引用的数据类型,在运行Pro*C/C++程序的时候,Oracle会根据需要将宿主变量的数据类型映射成Oracle外部数据类型,在编写Pro*C/C++程序的时候不能直接使用Oracle外部数据类型来定义宿主变量。
类型 | 说明 |
---|---|
VARCHAR2 | 变长字符串 |
NUMBER | 数字值 |
INTEGER | 有符号整数 |
FLOAT | 浮点数 |
STRING | 以NULL终止的变长字符串 |
VARNUM | 数字值,但包含数字长度 |
LONG | 长字符串 |
VARCHAR | 变长字符串 |
ROWID | 二进制值 |
DATE | 日期 |
VARRAW | 变长二进制 |
RAW | 定长二进制 |
LONG RAW | 定长二进制 |
UNSIGNED | 无符号整数 |
LONG VARCHAR | 变长字符串 |
LONG VARRAW | 变长二进制 |
CHAR | 定长字符 |
CHARZ | NULL终止定长字符串 |
CHARF | 等价CHAR的字符数据类型 |
MLSLABEL | 操作系统标记 |
外部数据类型包括全部的内部数据类型和宿主语言中所提供的几个数据类型
3.宿主类型
宿主变量数据类型也是SQL数据类型
1.
EXEC SQL VAR host_variable IS type_name[(length)];
char emp_name[11];
EXEC SQL VAR emp_name IS STRING(11);
2.用户定义类型等价
EXEC SQL TYPE user_type IS type_name[(length)];
typedef struct {
short len;
char buff[4000];
} graphics;
EXEC SQL TYPE graphics IS VARRAW(4000);
3.TO_DATE
例子:
typedef char dnameType[20];
typedef char locType[20];
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL TYPE dnameType is string(20);
EXEC SQL TYPE locType is string(20);
char *usrname = "myscott";
char *passwd = "22";
char *serverid = "orcl";
int deptno;
dnameType dname;
short dname_ind;
locType loc;
short loc_ind;
EXEC SQL END DECLARE SECTION;
EXEC SQL BEGIN DECLARE SECTION;
char *usrname = "scott";
char *passwd = "tiger";
char *serverid = "orcl";
int count;
int deptno[100];
char dname[100][20];
char loc[100][20];
int deptno2[100];
varchar dname2[100][20]; //varchar类型 和 char 类型的区别
varchar loc2[100][20];
EXEC SQL END DECLARE SECTION;
预先定义了
EXEC SQL BEGIN DECLARE SECTION;
int deptid = 50;
char dname[32] = "20name";
char loc[32] = "20loc";
EXEC SQL END DECLARE SECTION;
1.插入数据
EXEC SQL insert into dept(DEPTNO,DNAME,LOC) values(:deptid,:dname,:loc);
2.删除数据
EXEC SQL delete from dept where deptno=:deptid;
3.修改数据
EXEC SQL update dept set loc = :loc where deptno=:deptid;
综合实例:
#include
#include
#include
#include
#include "sqlca.h"
//定义宿主变量(SQL变量)
//C语言可以直接使用
//嵌入式SQL语句里面使用的话需要加上EXEC SQL前缀
EXEC SQL BEGIN DECLARE SECTION;
//char * serverid = "scott/lzj123529";
char user[32];
char passwd[32];
char sid[32];
int deptid = 50;
char dname[32] = "20name";
char loc[32] = "20loc";
EXEC SQL END DECLARE SECTION;
int main()
{
int ret = 0;
printf("HelloWorld\n");
printf("\nuser:");
scanf("%s",user);
printf("\npasswd:");
scanf("%s",passwd);
printf("sid:");
scanf("%s",sid);
EXEC SQL CONNECT:user IDENTIFIED BY:passwd USING:sid;
if(sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode ;
printf("ret :%d\n",ret);
return ret;
}
printf("connect OK!\n");
EXEC SQL insert into dept(DEPTNO,DNAME,LOC) values(:deptid,:dname,:loc);
EXEC SQL COMMIT;//提交事务不退出
sleep(10);
printf("delete ....\n");
//EXEC SQL delete from dept where deptno=:deptid;
strcpy(loc,"中国");
EXEC SQL update dept set loc = :loc where deptno=:deptid;
EXEC SQL COMMIT RELEASE;//提交事务并且断开
return 0;
}
EXEC SQL WHENEVER
condition:
SQLWARNING
SQLERROR
NOT FOUND 编译选项 MODE=ORACLE sqlca.sqlcode = 1403
编译选项 MODE=ANSI sqlca.sqlcode = 100
aciton:
CONTINUE
DO
GOTO label_name
STOP
EXEC SQL WHENEVER SQLERROR GOTO connect_error;
...
connect_error:
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK RELEASE;
printf("\nInvalid username/password\n");
exit(1);
完整示例:
#include
#include
#include
#include "sqlca.h"
//连接数据
//先定义宿主变量 (SQL变量)
EXEC SQL BEGIN DECLARE SECTION ;
char * serverid = "scott/tiger2@orcl";
int deptid;
char DNAME[32];
char LOC[32];
EXEC SQL END DECLARE SECTION ;
//错误SQL语言给打印出来
void sqlerr02()
{
char stm[120];
size_t sqlfc, stmlen=120;
unsigned int ret = 0;
printf("func sqlerr02() begin\n");
//出错时,可以把错误SQL语言给打印出来
EXEC SQL WHENEVER SQLERROR CONTINUE;
ret = sqlgls(stm, &stmlen, &sqlfc);
/*
if (ret != 0)
{
printf("func sqlgls() err, %d \n", ret);
return ;
}*/
printf("中国\n");
printf("出错的SQL:%.*s\n", stmlen, stm);
printf("出错原因:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
//printf("出错原因:%.70s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
printf("func sqlerr02() end\n");
exit(1);
}
//出错原因
void sqlerr()
{
EXEC SQL WHENEVER SQLERROR CONTINUE; // 下一步
printf("err reason:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
//printf("err reason:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;//
exit(1);
}
int main()
{
int ret = 0;
printf("hello....\n");
printf("serverid:%s \n", serverid);
deptid = 63;
strcpy(DNAME, "50name");
strcpy(LOC, "50loc");
EXEC SQL WHENEVER SQLERROR DO sqlerr();
EXEC SQL connect :serverid;
if (sqlca.sqlcode != 0)
{
ret = sqlca.sqlcode ;
printf("connect err:%d \n", ret);
return ret;
}
else
{
printf("connect ok\n");
}
EXEC SQL insert into dept(DEPTNO, DNAME, LOC) values(:deptid, :DNAME, :LOC);
EXEC SQL COMMIT;
printf("anter key continue ...delete...\n");
getchar();
getchar();
//EXEC SQL delete from dept where deptno= :deptid;
printf("anter key continue ...update...\n");
getchar();
getchar();
strcpy(LOC, "50loclolo");
strcpy(LOC, "中国");
EXEC SQL update dept set loc= :LOC where deptno= :deptid;
EXEC SQL COMMIT RELEASE; //提交事务断开连接
return ret;
}
$ locate stddef.h
把对应的头文件路径添加到Proc的配置文件(pcscfg.cfg)里面
$ oerr ora 错误码