此部分介绍如何打开、关闭和切换数据库连接。
使用以下语句连接到数据库
EXEC SQL CONNECT TOtarget
[ASconnection-name
] [USERuser-name
];
可以用以下方法指定 target
dbname
[@hostname
][:port
]
tcp:postgresql://hostname
[:port
][/dbname
][?options
]
unix:postgresql://127.0.0.1[:port
][/dbname
][?options
]
DEFAULT
连接目标 DEFAULT
将使用默认用户名初始化与默认数据库的连接。在这种情况下不能指定单独的用户名或连接名称。
如果您直接指定连接目标 (即,不是字符串文字或变量引用),那么目标的组件将通过常规 SQL 解析传递;也就是说,例如,hostname
必须类似于用点分隔的一个或多个 SQL 标识符,除非使用双引号将这些标识符区分大小写。任何 options
的值必须是 SQL 标识符、整数或变量引用。当然,您可以使用双引号将几乎任何内容放入 SQL 标识符中。实际上,使用 (单引号) 字符串文字或变量引用可能比直接编写连接目标更不易出错。
也有不同的方法来指定用户名
username
username
/password
username
IDENTIFIED BY password
username
USING password
如上所述,参数 username
和 password
可以是 SQL 标识符、SQL 字符串文字或引用字符变量。
如果连接目标包括任何 options
,那么这些 options
由使用和号 (&
) 分隔的
规范组成。允许的关键字与 libpq 识别的关键字相同 (请参见 第 32.1.2 节)。任何 keyword
=value
keyword
或 value
之前都会忽略空格,但它们内部或之后不会忽略空格。请注意,没有办法在 value
注意,指定套接字连接(带有前缀 unix:
)时,主机名必须完全等于 localhost
。要选择非默认套接字目录,请将目录的路径名作为 target 的 options
部分中 host
选项的值写入。
connection-name
用于在一个程序中处理多个连接。如果一个程序只使用一个连接,可以省略它。最近打开的连接成为当前连接,在执行 SQL 语句时会默认使用它(参见本章后面的内容)。
以下是 CONNECT
语句的示例
EXEC SQL CONNECT TO [email protected]; EXEC SQL CONNECT TO tcp:postgresql://sql.mydomain.com/mydb AS myconnection USER john; EXEC SQL BEGIN DECLARE SECTION; const char *target = "[email protected]"; const char *user = "john"; const char *passwd = "secret"; EXEC SQL END DECLARE SECTION; ... EXEC SQL CONNECT TO :target USER :user USING :passwd; /* or EXEC SQL CONNECT TO :target USER :user/:passwd; */
最后一个示例使用了上述作为字符变量引用的特性。在后面的部分中,你将看到如何使用 C 变量,只需在 C 变量前加上冒号即可。
请注意,SQL 标准中没有指定连接目标的格式。因此,如果你想开发可移植应用程序,也许可以将最后一个示例用作基础,将连接目标字符串封装在某处。
如果不受信任的用户可以访问尚未采用 安全架构用法模式 的数据库,在每次会话中都从 search_path
中删除可公开写入的架构。例如,将 options=-c search_path=
添加到
,或在连接后发出 options
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false);
。此考量并非 ECPG 特有,它适用于执行任意 SQL 命令的每个接口。
嵌入式 SQL 程序中的 SQL 语句在默认情况下会执行当前连接(即最近打开的连接)。如果某个应用程序需要管理多个连接,则有三种方法可以处理此问题。
第一个选择是为每个 SQL 语句明确选择一个连接,例如
EXEC SQL AT connection-name
SELECT ...;
如果应用程序需要按照混合顺序使用多个连接,此选项特别合适。
如果你的应用程序使用多个执行线程,它们不能同时共享连接。你必须明确控制对连接的访问(使用互斥量)或为每个线程使用一个连接。
第二个选择是执行一个语句来切换当前连接。该语句为
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 SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; EXEC SQL CONNECT TO testdb2 AS con2 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; EXEC SQL CONNECT TO testdb3 AS con3 USER testuser; EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT; /* This query would be executed in the last opened database "testdb3". */ EXEC SQL SELECT current_database() INTO :dbname; printf("current=%s (should be testdb3)\n", dbname); /* Using "AT" to run a query in "testdb2" */ EXEC SQL AT con2 SELECT current_database() INTO :dbname; printf("current=%s (should be testdb2)\n", dbname); /* Switch the current connection to "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)
第三个选择是声明一个链接到连接的 SQL 标识符,例如
EXEC SQL ATconnection-name
DECLAREstatement-name
STATEMENT; EXEC SQL PREPAREstatement-name
FROM :dyn-string
;
一旦将 SQL 标识符链接到连接,即可在没有 AT 子句的情况下执行动态 SQL。请注意,此选项的行为就像预处理器指令,因此链接仅在该文件中启用。
这里有使用此选项的示例程序
#include <stdio.h> EXEC SQL BEGIN DECLARE SECTION; char dbname[128]; char *dyn_sql = "SELECT current_database()"; EXEC SQL END DECLARE SECTION; int main(){ EXEC SQL CONNECT TO postgres AS con1; EXEC SQL CONNECT TO testdb AS con2; EXEC SQL AT con1 DECLARE stmt STATEMENT; EXEC SQL PREPARE stmt FROM :dyn_sql; EXEC SQL EXECUTE stmt INTO :dbname; printf("%s\n", dbname); EXEC SQL DISCONNECT ALL; return 0; }
此示例将生成此输出,即使默认连接为 testdb
postgres
若要关闭连接,请使用以下语句
EXEC SQL DISCONNECT [connection
];
可以使用以下方式指定 connection
connection-name
CURRENT
ALL
如果未指定连接名称,则当前连接将关闭。
良好的风格是应用程序始终显式断开与其打开的每个连接的连接。