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

34.5. 動態 SQL #

在許多情況下,應用程式需要執行的特定 SQL 語句在應用程式編寫時就已經知道了。然而,在某些情況下,SQL 語句是在執行時組合的,或者由外部源提供。在這些情況下,您不能將 SQL 語句直接嵌入到 C 原始碼中,但有一種機制允許您呼叫在字串變數中提供的任意 SQL 語句。

34.5.1. 執行不帶結果集的語句 #

執行任意 SQL 語句的最簡單方法是使用 EXECUTE IMMEDIATE 命令。例如:

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "CREATE TABLE test1 (...);";
EXEC SQL END DECLARE SECTION;

EXEC SQL EXECUTE IMMEDIATE :stmt;

EXECUTE IMMEDIATE 可用於不返回結果集的 SQL 語句(例如,DDL、INSERTUPDATEDELETE)。您不能透過這種方式執行檢索資料的語句(例如,SELECT)。下一節將介紹如何做到這一點。

34.5.2. 執行帶輸入引數的語句 #

執行任意 SQL 語句的更強大方法是準備一次語句,然後根據需要多次執行準備好的語句。還可以準備一個語句的通用版本,然後透過替換引數來執行該語句的特定版本。在準備語句時,在您希望稍後替換引數的位置寫上問號。例如:

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE mystmt FROM :stmt;
 ...
EXEC SQL EXECUTE mystmt USING 42, 'foobar';

當您不再需要準備好的語句時,應該將其釋放:

EXEC SQL DEALLOCATE PREPARE name;

34.5.3. 執行帶結果集的語句 #

要執行帶單個結果行的 SQL 語句,可以使用 EXECUTE。要儲存結果,請新增 INTO 子句。

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?";
int v1, v2;
VARCHAR v3[50];
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE mystmt FROM :stmt;
 ...
EXEC SQL EXECUTE mystmt INTO :v1, :v2, :v3 USING 37;

EXECUTE 命令可以帶有 INTO 子句、USING 子句、兩者都有,或者兩者都沒有。

如果查詢預計返回多於一個結果行,則應使用遊標,如下例所示。(有關遊標的更多詳細資訊,請參閱第 34.3.2 節。)

EXEC SQL BEGIN DECLARE SECTION;
char dbaname[128];
char datname[128];
char *stmt = "SELECT u.usename as dbaname, d.datname "
             "  FROM pg_database d, pg_user u "
             "  WHERE d.datdba = u.usesysid";
EXEC SQL END DECLARE SECTION;

EXEC SQL CONNECT TO testdb AS con1 USER testuser;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;

EXEC SQL PREPARE stmt1 FROM :stmt;

EXEC SQL DECLARE cursor1 CURSOR FOR stmt1;
EXEC SQL OPEN cursor1;

EXEC SQL WHENEVER NOT FOUND DO BREAK;

while (1)
{
    EXEC SQL FETCH cursor1 INTO :dbaname,:datname;
    printf("dbaname=%s, datname=%s\n", dbaname, datname);
}

EXEC SQL CLOSE cursor1;

EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;

提交更正

如果您在文件中發現任何不正確、不符合您對特定功能的經驗,或需要進一步澄清的內容,請使用此表單報告文件問題。