管理数据库连接
连接数据库
使用如下语句连接数据库:
EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];
- dbname[@hostname][:port]
- tcp:gaussdb://hostname[:port][/dbname][?options]
- unix:gaussdb://hostname[:port][/dbname][?options]
ecpg支持IPv6格式,需要在hostname两端添加方括号“[]”。
IPv6格式示例如下:
db1@[::1] db1@[::1]:5432 tcp:gaussdb://[::1]/db1 tcp:gaussdb://[::1]:5432/db1 unix:gaussdb://[::1]/db1 unix:gaussdb://[::1]:5432/db1
目前ecpg支持的IPv6格式如下:
- 简写大写格式
- 简写小写格式
- 非简写大写格式
- 非简写小写格式
IPv6的回环地址为::1或者0:0:0:0:0:0:0:1,因此Unix协议在IPv6下只支持这两种格式。
- username/password
- username SQLIDENTIFIED BY password
- username USING password
如上所述,参数username以及password可以是一个SQL标识符、一个SQL字符串或一个对字符变量的引用。
connection-name表示连接名,如果一个程序仅使用一个连接,可以省略connection-name;若使用多个连接,则最近打开的连接将作为当前连接。
- 若连接语句中指定了ip-port,则必须指定username/password,该规则由内核通信认证所决定。若不指定ip-port,则通过本地$PGPORT(UDS协议)进行通信。
- 若客户连接时使用SSL安全协议,则需要使用tcp:gaussdb://hostname[:port][/dbname][?options]连接格式,在options选项中配置sslmode=disable/require。
#include <stdlib.h>
EXEC SQL CONNECT TO mydb@sql.mydomain.com;
EXEC SQL CONNECT TO unix:gaussdb://sql.mydomain.com/mydb AS myconnection USER username;
EXEC SQL BEGIN DECLARE SECTION;
/* 此处target、user、passwd应从环境变量或配置文件读取,环境变量需用户自己按需配置;非环境变量情况下可直接赋值字符串 */
const char *target = getenv("EXAMPLE_TARGET_ENV");
const char *user = getenv("EXAMPLE_USERNAME_ENV");
const char *passwd = getenv("EXAMPLE_PASSWD_ENV");
EXEC SQL END DECLARE SECTION;
...
EXEC SQL CONNECT TO :target USER :user USING :passwd;
/* 或者 EXEC SQL CONNECT TO :target USER :user/:passwd; */ 完整使用示例,请参见CONNECT中的“连接语法使用示例”。
管理连接
默认情况下,嵌入式SQL-C程序中的语句均在当前连接(即最近创建的连接)上执行。当应用需要并发处理多个数据库实例时,可通过以下两种方式进行连接路由:
- 方法1:为每个SQL语句明确指定一个连接:
EXEC SQL AT connection-name SELECT ...;
适用于应用程序以混合顺序使用多个连接的情况。
- 方法2:执行一个语句来切换连接:
EXEC SQL SET CONNECTION connection-name;
适用于多个语句在同一个连接上执行的场景。
#include <stdio.h>
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
EXEC SQL END DECLARE SECTION;
int main()
{
EXEC SQL CONNECT TO testdb1 AS con1 USER testuser;
EXEC SQL CONNECT TO testdb2 AS con2 USER testuser;
EXEC SQL CONNECT TO testdb3 AS con3 USER testuser;
/* 这个查询将在最近连接的数据库 "testdb3" 中执行 */
EXEC SQL SELECT current_database() INTO :dbname;
printf("current=%s (should be testdb3)\n", dbname);
/* 使用 "AT" 在 "testdb2" 中运行一个查询 */
EXEC SQL AT con2 SELECT current_database() INTO :dbname;
printf("current=%s (should be testdb2)\n", dbname);
/* 切换当前连接到 "testdb1" */
EXEC SQL SET CONNECTION con1;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current=%s (should be testdb1)\n", dbname);
EXEC SQL DISCONNECT ALL;
return 0;
} 运行结果如下:
current=testdb3 (should be testdb3) current=testdb2 (should be testdb2) current=testdb1 (should be testdb1)
- 多线程模式下不支持不同线程使用同一连接名,每个线程连接名唯一。
- 连接的建立和关闭需要在同一进程或线程中进行。
- 如果应用程序创建多个执行线程,它们不能共享同一个连接,必须明确控制对连接的访问(比如利用互斥量)或者每个线程使用一个唯一 连接。