2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3

34.2. 管理資料庫連線 #

本節介紹如何開啟、關閉和切換資料庫連線。

34.2.1. 連線到資料庫伺服器 #

使用以下語句連線到資料庫

EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];

目標 可以透過以下方式指定

  • 資料庫名[@主機名][:]
  • tcp:postgresql://主機名[:][/資料庫名][?選項]
  • unix:postgresql://[:][/資料庫名][?選項]
  • 一個包含上述形式之一的 SQL 字串字面量
  • 一個包含上述形式之一的字元變數的引用(參見示例)
  • DEFAULT

連線目標 DEFAULT 會在預設使用者名稱下啟動到一個預設資料庫的連線。在這種情況下,不能指定單獨的使用者名稱或連線名。

如果您直接指定連線目標(即,不是作為字串字面量或變數引用),則目標的組成部分將透過正常的 SQL 解析;這意味著,例如,主機名 必須看起來像一個或多個由點分隔的 SQL 識別符號,並且除非加雙引號,否則這些識別符號將是大小寫摺疊的。任何 選項 的值必須是 SQL 識別符號、整數或變數引用。當然,您可以透過加雙引號將幾乎任何內容放入 SQL 識別符號中。實際上,使用(單引號)字串字面量或變數引用可能比直接編寫連線目標更不容易出錯。

還有不同的指定使用者名稱的方法

  • 使用者名稱
  • 使用者名稱/密碼
  • 使用者名稱 IDENTIFIED BY 密碼
  • 使用者名稱 USING 密碼

與上面一樣,使用者名稱密碼 引數可以是 SQL 識別符號、SQL 字串字面量或字元變數的引用。

如果連線目標包含任何 選項,那麼這些選項是由 關鍵字= 規範組成的,並由和號(&)分隔。允許的關鍵字與 libpq 識別的關鍵字相同(參見 第 32.1.2 節)。在任何 關鍵字 之前都會忽略空格,但在其內部或之後則不會。請注意,無法在 中寫入 &

請注意,當指定套接字連線(帶有 unix: 字首)時,主機名必須是 localhost。要選擇一個非預設套接字目錄,請在目標 選項 部分將目錄的路徑名作為 host 選項的值來編寫。

連線名 用於處理程式中的多個連線。如果程式只使用一個連線,則可以省略它。最近開啟的連線將成為當前連線,當執行 SQL 語句時(本章稍後介紹)將預設使用該連線。

以下是一些 CONNECT 語句的示例

EXEC SQL CONNECT TO mydb@sql.mydomain.com;

EXEC SQL CONNECT TO tcp:postgresql://sql.mydomain.com/mydb AS myconnection USER john;

EXEC SQL BEGIN DECLARE SECTION;
const char *target = "mydb@sql.mydomain.com";
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 變數可以在 SQL 語句中使用。

請注意,連線目標的格式未在 SQL 標準中指定。因此,如果您想開發可移植的應用程式,您可能需要使用上面最後一個示例的某種形式來將連線目標字串封裝到某個地方。

如果不受信任的使用者可以訪問尚未採用 安全模式使用模式 的資料庫,請在每個會話開始時從 search_path 中移除可公開寫入的模式。例如,將 options=-c search_path= 新增到 options 中,或者在連線後執行 EXEC SQL SELECT pg_catalog.set_config('search_path', '', false);。此考慮因素並非 ECPG 特有;它適用於執行任意 SQL 命令的每個介面。

34.2.2. 選擇連線 #

嵌入式 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 AT connection-name DECLARE statement-name STATEMENT;
EXEC SQL PREPARE statement-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

34.2.3. 關閉連線 #

要關閉連線,請使用以下語句

EXEC SQL DISCONNECT [connection];

連線 可以透過以下方式指定

  • 連線名
  • CURRENT
  • ALL

如果未指定連線名,則會關閉當前連線。

應用程式最好始終顯式斷開它開啟的所有連線。

提交更正

如果您在文件中看到任何不正確的內容、與您對特定功能的實際體驗不符或需要進一步說明的內容,請使用 此表單 報告文件問題。