SQL 语言作为结构化的查询语言,可以完成对数据库的定义、查询、更新、控制、维护、恢复、安全管理等一系列操作,充分体现了关系数据库的特征。但 SQL 语言是非过程性语言,本身没有过程性结构,大多数语句都是独立执行,与上下文无关,而绝大多数完整的应用都是过程性的,需要根据不同的条件来执行不同的任务。因此,单纯用 SQL 语言很难实现这样的应用,DM 数据库提供了 SQL 的两种使用方式:
嵌入方式是将 SQL 语言嵌入到高级语言中,这样一来,既发挥了高级语言数据类型丰富、处理方便灵活的优势,又以 SQL 语言弥补了高级语言难以描述数据库操作的不足,从而为用户提供了建立大型管理信息系统和处理复杂事务所需要的工作环境。
在这种方式下使用的 SQL 语言称为嵌入式 SQL,而嵌入 SQL 的高级语言称为主语言或宿主语言。DM 数据库允许 C 作为嵌入方式的主语言。在 DM 系统中,我们将嵌有 SQL 语句的 C 语言程序称为 PRO*C 程序。
开发环境搭建
软件
版本
DM 数据库
DM 8.0 及以上版本
安装 DM 数据库 请参考 DM 数据库快速上手指南 。
数据库安装过程中,请勾选创建 BOOKSHOP,DMHR 示例库,作为数据库模拟环境,如下图所示:
gcc 环境检查 执行结果如下:
[root@localhost proctest]# gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
项目目录结构 proctest ├── proc_bind.c // 绑定变量示例 ├── proc_conn.c // 数据库连接示例 ├── proc_dml.c // 基本操作示例 ├── proc_lob.c // 大字段操作示例 ├── file // 大字段操作示例中导入和导出文件目录 | ├── DM8_SQL.pdf // 大字段操作示例中导入文件 ├── makfile // makefile 编译脚本
makefile 脚本如下:
[root@RS1821 proctest]# cat makefile CC=gcc includepath=$(DM_HOME)/include libpath=$(DM_HOME)/bin vpath=./ CFLAGS=-I$(includepath) -DDM64 -Wall LINKFLAGS=-L$(libpath) -ldmdpc -Wall -Wl,-rpath $(libpath) % .c:%.pc $(DM_HOME)/bin/dpc_new file=$< % .o:%.c $(CC) -g -c $(CFLAGS) $< -o $@ object_file1=proc_conn.o object_file2=proc_dml.o object_file3=proc_bind.o object_file4=proc_lob.o object_files=proc_conn.o proc_dml.o proc_bind.o proc_lob.o final_objects=proc_conn proc_dml proc_bind proc_lob all : $(final_objects) .PHONY : all clean rebuild proc_conn : $(object_file1) $(CC) -o $@ $(object_file1) -g $(LINKFLAGS) @echo make ok. proc_dml : $(object_file2) $(CC) -o $@ $(object_file2) -g $(LINKFLAGS) @echo make ok. proc_bind : $(object_file3) $(CC) -o $@ $(object_file3) -g $(LINKFLAGS) @echo make ok. proc_lob : $(object_file4) $(CC) -o $@ $(object_file4) -g $(LINKFLAGS) @echo make ok. clean : @rm -rf $(object_files) @rm -rf $(final_objects) rebuild : clean all
数据库连接 数据库连接示例 PROC*C 接口登录登出示例程序 proc_conn.c 如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> EXEC SQL INCLUDE SQLCA; EXEC SQL BEGIN DECLARE SECTION; char username[10 ]="SYSDBA" ;char password[10 ]="SYSDBA" ;char dbserver[20 ]="localhost:51236" ;EXEC SQL END DECLARE SECTION; int main () { EXEC SQL LOGIN :username PASSWORD :password SERVER :dbserver; if ( sqlca.sqlcode!=0 ) { printf ( "login fail![%d, %s]\n" , sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc ) ; exit (-1 ); } printf ( "proc:conn to server success\n" ); EXEC SQL LOGOUT; return 0 ; }
执行结果如下:
[root@RS1821 proctest]# ./proc_conn proc: conn to server success [root@RS1821 proctest]#
开发示例 基本操作示例 PROC*C 接口增、删、改、查四个基本操作,示例程序 proc_dml.c 如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> EXEC SQL INCLUDE SQLCA; EXEC SQL BEGIN DECLARE SECTION; char username[10 ]="SYSDBA" ;char password[10 ]="SYSDBA" ;char dbserver[20 ]="192.168.104.21:51236" ;int c1 = 0 ;char c2[51 ] = {0 };EXEC SQL END DECLARE SECTION; int main () { EXEC SQL LOGIN :username PASSWORD :password SERVER :dbserver; if ( sqlca.sqlcode!=0 ) { printf ( "login fail![%d, %s]\n" , sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc ) ; exit (-1 ); } printf ( "proc: conn to server success\n" ) ; EXEC SQL DELETE FROM PRODUCTION.PRODUCT_CATEGORY; EXEC SQL COMMIT; EXEC SQL INSERT INTO PRODUCTION.PRODUCT_CATEGORY(NAME) VALUES('语文'), ('数学'), ('英语'), ('体育'); EXEC SQL COMMIT; EXEC SQL DELETE PRODUCTION.PRODUCT_CATEGORY WHERE NAME='数学'; EXEC SQL COMMIT; EXEC SQL UPDATE PRODUCTION.PRODUCT_CATEGORY SET NAME='英语-新课标' WHERE NAME='英语'; EXEC SQL COMMIT; EXEC SQL DECLARE t_cur CURSOR FOR SELECT * FROM PRODUCTION.PRODUCT_CATEGORY; EXEC SQL OPEN t_cur; EXEC SQL WHENEVER NOT FOUND GOTO NEXTONE; for (;;) { EXEC SQL FETCH t_cur INTO :c1,:c2; printf ("%d\t%s\n" , c1, c2); } NEXTONE: EXEC SQL WHENEVER NOT FOUND CONTINUE; EXEC SQL CLOSE t_cur ; EXEC SQL LOGOUT; return 0 ; }
执行结果如下:
[root@RS1821 proctest]# ./proc_dml proc: conn to server success 34 语文 36 英语-新课标 37 体育
绑定变量示例 PROC*C 接口绑定变量示例程序 proc_bind.c 如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> EXEC SQL INCLUDE SQLCA; EXEC SQL BEGIN DECLARE SECTION; char username[10 ]="SYSDBA" ;char password[10 ]="SYSDBA" ;char dbserver[20 ]="192.168.104.21:51236" ;int c1_out = 0 ;char c2_in[51 ] = "物理" ;char c2_out[51 ] = {0 };char sql[128 ] = {0 };EXEC SQL END DECLARE SECTION; int main () { EXEC SQL LOGIN :username PASSWORD :password SERVER :dbserver; if ( sqlca.sqlcode!=0 ) { printf ( "login fail![%d, %s]\n" , sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc ) ; exit (-1 ); } printf ( "proc: conn to server success\n" ) ; EXEC SQL DELETE FROM PRODUCTION.PRODUCT_CATEGORY; EXEC SQL COMMIT; strcpy ((char *)sql,"INSERT INTO PRODUCTION.PRODUCT_CATEGORY(NAME) VALUES(?)" ); EXEC SQL PREPARE stmt FROM :sql; EXEC SQL EXECUTE stmt USING :c2_in; EXEC SQL COMMIT; EXEC SQL DECLARE t_cur CURSOR FOR SELECT * FROM PRODUCTION.PRODUCT_CATEGORY; EXEC SQL OPEN t_cur; EXEC SQL WHENEVER NOT FOUND GOTO NEXTONE; for (;;) { EXEC SQL FETCH t_cur INTO :c1_out,:c2_out; printf ("%d\t%s\n" , c1_out, c2_out); } NEXTONE: EXEC SQL WHENEVER NOT FOUND CONTINUE; EXEC SQL CLOSE t_cur ; EXEC SQL LOGOUT; return 0 ; }
执行结果如下:
[root@RS1821 proctest]# ./proc_bind proc: conn to server success 38 物理