[SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)

目录

一、环境安装

二、环境配置

三、编写程序


一、环境安装

1.PostgreSQL10.23 X64(应该哪个版本都行);

(1)由于使用 EXEC SQL 这种嵌入方式已经非常古老,近些年的Mysql和SQL Server都已经不支持这种嵌入,因此使用 PostgreSQL。

(2)SQL Server 2000 版本似乎可以,但没试过。

(3)下载及安装查看:https://www.runoob.com/postgresql/windows-install-postgresql.html

2.Microsoft Viusal Studio 2017(vs其他版本、dev-cpp、codeblocks也行)。

二、环境配置

1.打开项目属性

2.将 [调试] 中的 [环境] 改为 bin 文件夹地址

[SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)_第1张图片

3.将 [C++-常规] 中的 [附加库包含目录] 改为 include 文件夹地址

[SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)_第2张图片

4.将 [链接器-常规] 中的 [附加库目录] 改为 lib 文件夹地址

[SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)_第3张图片

 5.将 [链接器-输入] 中的 [附加依赖项] 加上 libecpg.lib 的地址

[SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)_第4张图片

 6.在 PostgreSQL 的安装目录下,找到 bin 文件夹,从 bin 文件夹中拷贝下面七个 dll 至项目文件夹 [SQL | 嵌入式] 如何在高级语言中使用 EXEC SQL 语法(PostgreSQL + C)_第5张图片

 7.将运行平台修改为 X64

三、编写程序

1.先了解一些东西

(1)EXEC SQL 这种嵌入方式,是不能写在任何一种高级程序语言中的。

因此DBMS会采用预编译方法处理。他们通常提供一个预处理器(.exe),当我们写好了预处理文件后,使用预处理器将预处理文件转换成宿主语言的标准文件,这个时候就可以使用高级语言的编译器运行了。

(2)不同的 DBMS 有不同的预处理文件格式,我们即将使用的 PostgreSQL 就是以(.pgc)作为格式。预处理器将该种文件处理过后,就会生成(.c)文件。

PostgreSQL 的预处理命令:(按照自己的路径去写即可)

(3)总结上面两点:当我们写好 预处理文件,就使用 预处理器 进行编译,接着运行预处理器产生的主语言程序即可。

2.编写程序

(1)首先我们知道,每一次 EXEC SQL 都相当于在命令行中写入一条语句。

(2)在预处理文件中,只要与 EXEC SQL 语句沾点边的变量,都必须在 main() 前进行声明,也就是主变量声明。

(3)在 PostgreSQL 中,连接到一个数据库后,只能对这个数据库内的表操作。

(4)其余看代码注释,下面是 预处理文件.pgc


#include "stdio.h"
#include "stdlib.h"
#include "string.h"

// 相当于高级程序语言的全局变量定义

EXEC SQL BEGIN DECLARE SECTION; // 主变量声明开始

const char* target1 = "postgres@localhost:5432"; // 数据库1
const char* user1 = "postgres";
const char* passwd1 = "123456";

const char* target2 = "spj@localhost:5432"; // 数据库2
const char* user2 = "postgres";
const char* passwd2 = "123456";


int rows = 0; // 表行数

char sno[10]; // s表的四个属性(s表是自定义的)
char sname[20];
int status;
char city[20];

EXEC SQL END DECLARE SECTION; // 主变量声明结束

int main() {
	EXEC SQL WHENEVER SQLERROR SQLPRINT; // error 时输出错误信息

	// 连接至数据库1
	EXEC SQL CONNECT TO :target1 USER :user1 USING :passwd1;
	printf("\n已连接%s\n", target1);

	EXEC SQL drop database if exists spj; // 删除 spj 数据库
	EXEC SQL create database spj; // 创建 spj 数据库

	// 断开数据库1
	EXEC SQL DISCONNECT CURRENT; // 这个不写也能运行,不知道有没有风险
	printf("\n已断开%s\n", target1);


	// 连接至数据库2
	EXEC SQL CONNECT TO :target2 USER :user2 USING :passwd2;
	printf("\n已连接%s\n", target2);

	// 下面五条exec sql,建表及插入
	EXEC SQL drop table if exists s;
	EXEC SQL CREATE TABLE IF NOT EXISTS s(sno char(10) primary key, sname char(20) unique, status int, city char(20));
	EXEC SQL insert into s(sno, sname, status, city) values('s1', 'APEX LEGEND', 114514, 'Wuhan'); 
	EXEC SQL insert into s(sno, sname, status, city) values('s2', 'DEVIL MAY CRY5', 616161, 'Wuhan');
	EXEC SQL insert into s(sno, sname, status, city) values('s3', 'WARFRAME', 123456, 'Wuhan');
	// 写入中文,数据库内是utf8,控制台输出的是gbk,会乱码

	
	EXEC SQL BEGIN; // BEGIN 事务块,DECLARE只能在事务块中使用

	// 定义游标,相当于每次读表的一行
	EXEC SQL DECLARE iterator CURSOR FOR 
				select sno, sname, status, city
				from s;

	EXEC SQL OPEN iterator; // 打开游标

	EXEC SQL select count(*) into :rows from s; // 获取行数,只有主变量能被sql赋值

	int flag = 0;
	while (rows --) {
		EXEC SQL fetch iterator into :sno, :sname, :status, :city; // fetch 获取一行元组
		
		if (flag ++ == 0) { // 第一次把列名输出
			printf("\n%-10s %-20s %-10s %-20s \n", "sno", "sname", "status", "city");
		}
		printf("%-10s %-20s %-10d %-20s \n", sno, sname, status, city);
	}
	EXEC SQL CLOSE iterator; // 关闭游标
	EXEC SQL END; // 结束事务块

	EXEC SQL DISCONNECT CURRENT; // 断开数据库2
	printf("\n已断开%s\n", target2);
	return 0;
}

动态SQL操作的代码:


#include "stdio.h"
#include "stdlib.h"
#include "string.h"

// 相当于高级程序语言的全局变量定义

EXEC SQL BEGIN DECLARE SECTION; // 主变量声明开始

const char* target = "postgres@localhost:5432"; // 数据库
const char* user = "postgres";
const char* passwd = "123456";

int rows = 0; // 表行数

// game表的属性(game表是自定义的)
char name[20];
int id;

const char *stmt = "insert into game values(?, ?);";

EXEC SQL END DECLARE SECTION; // 主变量声明结束

int main() {
	EXEC SQL WHENEVER SQLERROR SQLPRINT; // error 时输出错误信息

	// 连接至数据库
	EXEC SQL CONNECT TO :target USER :user USING :passwd;
	printf("\n已连接%s\n", target);

	EXEC SQL drop table if exists game;
	EXEC SQL create table game(id int primary key, name char(20));

	EXEC SQL prepare mystmt from :stmt;
	EXEC SQL execute mystmt using 1, 'Apex Legend';
	EXEC SQL execute mystmt using 2, 'Genshin';
	
	EXEC SQL BEGIN; // BEGIN 事务块,DECLARE只能在事务块中使用

	// 定义游标,相当于每次读表的一行
	EXEC SQL DECLARE iterator CURSOR FOR 
				select id, name
				from game;

	EXEC SQL OPEN iterator; // 打开游标

	EXEC SQL select count(*) into :rows from game; // 获取行数,只有主变量能被sql赋值

	int flag = 0;
	while (rows --) {
		EXEC SQL fetch iterator into :id, :name; // fetch 获取一行元组
		
		if (flag ++ == 0) { // 第一次把列名输出
			printf("\n%-10s %-20s \n", "id", "name");
		}
		printf("%-10d %-20s \n", id, name);
	}
	EXEC SQL CLOSE iterator; // 关闭游标
	EXEC SQL END; // 结束事务块

	EXEC SQL DISCONNECT CURRENT; // 断开数据库2
	printf("\n已断开%s\n", target);
	return 0;
}

本文介绍了二十几年前的嵌入式操作,欢迎纠错。

你可能感兴趣的:(PostgreSQL,postgresql,数据库)