
# 管理数据库连接
#### 连接数据库
使用如下语句连接数据库：
```
EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];
```
target可以通过如下方法声明，斜体部分为变量，请根据实际情况进行修改：
- *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
```
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
目前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；若使用多个连接，则最近打开的连接将作为当前连接。
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
- 若连接语句中指定了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](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0280.html)中的"连接语法使用示例"。
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
- 连接目标的格式未在SQL标准中说明，因此若要开发可移植的应用，可使用上述最后一个例子的方法将连接目标字符串封装在某个变量里。
- ecpg兼容性请参见[ecpg兼容](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0306.html#ZH-CN_TOPIC_0000002590200424__section8505927171)。
 
#### 管理连接
默认情况下，嵌入式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)
```
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
- 多线程模式下不支持不同线程使用同一连接名，每个线程连接名唯一。
- 连接的建立和关闭需要在同一进程或线程中进行。
- 如果应用程序创建多个执行线程，它们不能共享同一个连接，必须明确控制对连接的访问（比如利用互斥量）或者每个线程使用一个唯一 连接。
 
