PostgreSQL 動態(tài) SQL

2021-09-02 14:19 更新
35.5.1. 執(zhí)行沒有結(jié)果集的語句
35.5.2. 執(zhí)行一個有輸入?yún)?shù)的語句
35.5.3. 執(zhí)行一個有結(jié)果集的語句

在很多情況中,一個應(yīng)用必須要執(zhí)行的特定 SQL 語句在編寫該應(yīng)用時就已知。不過在某些情況中,SQL 語句在運行時構(gòu)造或者由一個外部來源提供。這樣你就不能直接把 SQL 語句嵌入到 C 源代碼,不過有一種功能允許你調(diào)用在一個字符串變量中提供的任意 SQL 語句。

35.5.1. 執(zhí)行沒有結(jié)果集的語句

執(zhí)行一個任意 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可以被用于不返回結(jié)果集的 SQL 語句(例如 DDL、INSERT、UPDATE、DELETE)。你不能用這種方法執(zhí)行檢索數(shù)據(jù)的語句(例如SELECT)。下一節(jié)將描述如何執(zhí)行這一種語句。

35.5.2. 執(zhí)行一個有輸入?yún)?shù)的語句

執(zhí)行任意 SQL 語句的一種更強大的方法是準備它們一次并且在每次需要時執(zhí)行該預備語句。也可以準備一個一般化的語句,然后通過替換參數(shù)執(zhí)行它的特定版本。在準備語句時,在你想要稍后替換參數(shù)的地方寫上問號。例如:

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';

當你不再需要預備語句時,你應(yīng)該釋放它:

EXEC SQL DEALLOCATE PREPARE name;

35.5.3. 執(zhí)行一個有結(jié)果集的語句

要執(zhí)行一個只有單一結(jié)果行的 SQL 語句,可以使用EXECUTE。要保存結(jié)果,在其中增加一個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子句,可以同時有這兩個子句,也可以不帶這兩個子句。

如果一個查詢被期望返回多于一個結(jié)果行,應(yīng)該如下列例子所示使用一個游標(關(guān)于游標詳見第 35.3.2 節(jié))。

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;


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號