| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 27. libpq - C 庫 | Fast Forward | Next |
一旦與數據庫服務器的連接成功建立,便可用這裡描述的函數執行 SQL 查詢和命令。
我們可以在命令行字串裡包含多個 SQL 命令(用分號分隔)。在一次 PQexec 調用中發送的多個查詢是在一個事務裡處理的,除非在查詢字串裡有明確的 BEGIN/COMMIT 命令用于把整個字串分隔成多個事務。請注意這樣返回的 PGresult 結構只描述字串裡執行的最後一條命令的結果。 如果有一個命令失敗,那麼字串處理的過程就會停止並且返回的 PGresult 會描述錯誤條件。
向服務器提交一條命令並且等待結果,還有額外的傳遞與 SQL 命令文本獨立的參數的能力。
PGresult *PQexecParams(PGconn *conn,
const char *command,
int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);PQexecParams 類似 PQexec,但是提供了額外的功能: 參數值可以獨立于命令串進行聲明,並且可以要求查詢結果的格式是文本或者二進制格式。 PQexecParams 只是在協議 3.0 以及以後的版本中支持;在使用 2.0 的版本的時候會失敗。
如果使用了參數,那麼它們是以 $1,$2,等等在命令字串中引用的。 nParams 是提供的參數的個數;它是數組 paramTypes[], paramValues[],paramLengths[],和 paramFormats[] 的長度。 (如果 nParams 是零,那麼數組指針可以是 NULL。) paramTypes[] 用 OID 的形式聲明了賦與參數符號的數據類型。 如果 paramTypes 是 NULL,或者數組中任意元素是零, 那麼服務器給對應的參數符號賦與和無類型文本串一樣的數據類型。 paramValues[] 聲明該參數的實際數值。這個數組中的空指針意味著對應的參數是空; 否則,這個指針指向一個空零結尾的文本字串(文本格式)或者服務器期待的格式的二進制數據(用于二進制格式)。 paramLengths[] 聲明二進制格式參數的實際數據長度。 對于空參數和文本格式的參數會忽略這個參數。如果沒有二進制參數,那麼這個數組指針可以是空。 paramFormats[] 聲明某個參數是文本(在數組中放一個零)還是二進制(在數組中放一個1)。 如果這個數組指針是空,那麼所有參數都認為是文本的。 resultFormat 為零則獲取以文本方式返回的結果,為一則獲取以二進制形式返回的結果。 (目前不能規定從不同的字段獲取不同格式的結果,盡管對下層的協議是可能的。)
PQexecParams 比 PQexec 最主要的優勢是我們可以和命令串分開聲明參數值, 這樣就可以避免枯燥無聊並且很容易出錯的引起和逃逸。 和 PQexec 不同的是,PQexecParams 在一個給出的字串裡最多允許一個 SQL 命令。 (裡面可以有分號,但是不得超過一個非空的命令。)這是下層的協議的一個限制, 但是也有些額外的好處,比如可以有另外一層防止 SQL 注射攻擊的層次。
發送一個請求,執行一個帶有給出參數的準備好的語句,並且等待結果。
PGresult *PQexecPrepared(PGconn *conn,
const char *stmtName,
int nParams,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);PQexecPrepared 和 PQexecParams 類似, 但是要執行的命令是通過命名一個前面準備好的語句聲明的,而不是給出一個查詢字串。 這個特性允許那些要重復使用的命令只進行一次分析和規劃,而不是每次執行都來一遍。 PQexecPrepared 只在協議 3.0 和以後的版本裡支持;在使用 2.0 版本的協議的時候,它們會失敗。
參數和 PQexecParams 一樣,只是給出的是一個準備好語句的名字,而不是一個查詢字串, 並且沒有 paramTypes[] 參數(沒必要,因為準備好語句的參數類型是在創建的時候確定的)。
目前,和 PQexecPrepared 一起用的準備好語句必須通過執行 PREPARE 命令來建立,通常是用 PQexec 發送(當然,任何 libpq 的查詢提交函數都可以使用)。 在將來的版本裡可能會提供一個低層次的準備語句的接口。
PGresult 結構封裝了服務器返回的結果。libpq 應該小心維護 PGresult 的抽象。 使用下面的訪問函數獲取 PGresult 的內容。避免直接引用 PGresult 裡面的字段, 因為它們在未來版本裡可能會被修改。
返回命令的結果狀態。
ExecStatusType PQresultStatus(const PGresult *res);
PQresultStatus可以返回下面數值之一:
發送給服務器的字串是空的
成功完成一個不返回數據的命令
成功執行一個返回數據的查詢查詢(比如 SELECT 或者 SHOW)。
(從服務器)Copy Out (拷貝出)數據傳輸開始
Copy In (拷貝入)(到服務器)數據傳輸開始
服務器的響應無法理解
發生了一個非致命錯誤(通知或者警告)
發生了一個致命錯誤
如果結果狀態是 PGRES_TUPLES_OK, 那麼可以用下面的函數從查詢的返回中抽取元組信息。 注意一個碰巧檢索了零條元組的SELECT仍然顯示 PGRES_TUPLES_OK。 PGRES_COMMAND_OK用于不返回元組的命令(INSERT,UPDATE,等)。 返回 PGRES_EMPTY_QUERY 的響應通常意味著暴露了客戶端軟件裡面的臭蟲。
狀態為 PGRES_NONFATAL_ERROR 的結果永遠不會直接由 PQexec 或者其它查詢執行函數返回;這類的結果會被傳遞給通知處理器(參閱 Section 27.9)。
把PQresultStatus返回的枚舉類型轉換成一個描述狀態碼的字符串常量。
char *PQresStatus(ExecStatusType status);
返回與查詢關聯的錯誤信息,或在沒有錯誤時返回一個空字符串。
char *PQresultErrorMessage(const PGresult *res);
如果有錯誤,那麼返回的字串將包括一個結尾的新行。
緊跟在一個 PQexec 或 PQgetResult 調用後面,PQerrorMessage (對連接)將返回與 PQresultErrorMessage (對結果)一樣的字符串。 不過,一個PGresult將保有其錯誤信息直到被刪除, 而連結的錯誤信息將在後續的操作完成時被改變。當你想知道與某個 PGresult相關聯的狀態時用 PQresultErrorMessage;當你想知道與連接的最近一個操作相關聯的狀態時用 PQerrorMessage。
PQclear 釋放于PGresult相關聯的存儲空間。 任何不再需要的查詢結果在不需要的時候都應該用PQclear釋放掉。
void PQclear(PQresult *res);
只要你需要,你可以保留PGresult對象任意長的時間; 當你提交新的查詢時它並不消失,甚至你斷開連接後也是這樣。 要刪除它,你必須調用 PQclear。不這麼做將導致你的應用中的內存洩漏。
構造一個帶有給出的狀態的,空的PGresult對象。
PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
這是libpq的內部函數, 用于分配和初始化一個空PGresult對象。 它被輸出是因為一些應用需要自行生成結果對象(尤其是特定的帶有錯誤狀態的對象)。 如果conn非空(NULL)並且狀態指示一個錯誤, 連接當前的錯誤信息被拷貝到PGresult。 注意最終對該對象還是要調用PQclear, 正如libpq本身返回的PGresult一樣。
這些函數用于從一個代表著成功查詢結果(也就是說,狀態為 PGRES_TUPLES_OK 的查詢) 的 PGresult 對象。對于其它狀態值的對象,他們的行為會好像他們有零行和零列一樣。
返回查詢結果裡的行(元組)個數。
int PQntuples(const PGresult *res);
返回查詢結果裡每個元組的數據域(字段)的個數。
int PQnfields(const PGresult *res);
返回與給出的數據域編號相關聯的數據域(字段)的名稱。數據域編號從 0 開始
char *PQfname(const PGresult *res, int column_number);
如果字段編號超出範圍,那麼返回NULL。
返回與給出的數據域名稱相關聯的數據域(字段)的編號。
int PQfnumber(const PGresult *res, const char *column_name);
如果給出的名字不匹配任何字段,返回 -1。
給出的名字是當作 SQL 命令裡的一個標識符看待的,也就是說,如果沒有加雙引號, 那麼會轉換為小寫。比如,如果我們有一個從 SQL 命令裡生成的查詢結果
select 1 as FOO, 2 as "BAR";
那麼我們會有下面的結果:
PQfname(res, 0) foo PQfname(res, 1) BAR PQfnumber(res, "FOO") 0 PQfnumber(res, "foo") 0 PQfnumber(res, "BAR") -1 PQfnumber(res, "\"BAR\"") 1
返回我們抓取的字段所在的表的 OID。字段編號從 0 開始。
Oid PQftable(const PGresult *res,
int column_number);如果字段編號超出了範圍,或者聲明的字段不是一個指向某個表的字段的簡單引用, 或者使用了 3.0 版本之前的協議,那麼就會返回 InvalidOid。 你可以查詢系統表 pg_class 來判斷究竟引用了哪個表。
在你包含 libpq 頭文件的時候, 就會定義類型 Oid 和常量 InvalidOid。 他們都是相同的整數類型。
返回組成聲明的查詢結果字段的字段號(在它的表內部)。結果字段號從 0 開始計數。
int PQftablecol(const PGresult *res,
int column_number);如果字段編號超出範圍,或者聲明的字段並不是一個表字段的簡單引用,或者使用的是 3.0 之前的協議,那麼返回零。
返回說明給出字段的格式的格式代碼。字段編號從 0 開始。
int PQfformat(const PGresult *res,
int column_number);格式碼為 0 表示文本數據,而格式碼是一表示二進制數據。(其它編碼保留給將來定義。)
返回與給定數據域編號關聯的數據域類型。 返回的整數是一個該類型的內部 OID 號。數據域編號從0 開始。
Oid PQftype(const PGresult *res, int column_number);
你可以查詢系統表 pg_type 以獲取各種數據類型的名稱和屬性。 內建的數據類型的 OID 在源碼樹的 src/include/catalog/pg_type.h 文件裡定義。
返回與給定字段編號相關聯的類型修飾詞。 字段編號從 0 開始。
int PQfmod(const PGresult *res, int column_number);
類型修飾符的值是類型相關的;他們通常包括精度或者尺寸限制。數值 -1 用于表示"沒有可用信息"。 大多數數據類型不用修飾詞,這種情況下該值總是 -1。
返回與給定字段編號關聯的字段以字節計的大小。 字段編號從0 開始。
int PQfsize(const PGresult *res, int column_number);
PQfsize返回在數據庫行裡面給該數據字段分配的空間, 換句話說就是該數據類型在服務器裡的二進制形式的大小(尺寸)。 (因此,這個對客戶端沒有什麼用。) 如果該數據域是可變尺寸,返回 -1。
如果PGresult包含二進制元組數據時返回 1, 如果包含 ASCII 數據返回 0。
int PQbinaryTuples(const PGresult *res);
這個函數已經廢棄了(除了還用于與 COPY 連接之外),因為我們可能在一個 PGresult 的某些字段裡包含文本數據,而另外一些字段包含二進制數據。 更好的是使用 PQfformat。 PQbinaryTuples 只有在結果中的所有字段都是二進制(格式 1)的時候才返回 1。
返回一個PGresult 裡面一行的單獨的一個字段的值。 行和字段編號從 0 開始。
char* PQgetvalue(const PGresult *res, int row_number, int column_number);
對于文本格式的數據, PQgetvalue 返回的值是一個表示字段值的空(NULL)結尾的字符串。 對于二進制格式, 返回的值就是由該數據類型的 typsend 和 typreceive 決定的二進制表現形式。 (在這種情況下,數值實際上也跟著一個字節零,但是通常這個字節沒什麼用處,因為數值本身很可能包含內嵌的空。)
如果字段值是空,則返回一個空字串。參閱 PQgetisnull 來區別空值和空字串值。
PQgetvalue 返回的指針指向一個本身是 PGresult結構的一部分的存儲區域。我們不能更改它, 並且如果我們要在PGresult結構的生存期後還要使用它的話, 我們必須明確地把該數值拷貝到其他存儲器中。
測試一個字段是否為空(NULL)。行和字段編號從 0 開始。
int PQgetisnull(const PGresult *res, int row_number, int column_number);
如果該域包含 NULL,函數返回 1,如果包含非空(non-null )值,返回 0。 (注意,對一個 NULL 數據域,PQgetvalue 將返回一個空字符串, 不是一個空指針。)
返回以字節計的字段的長度。行和字段編號從 0 開始。
int PQgetlength(const PGresult *res, int row_number, int column_number);
這是某一特定數據值的實際數據長度。 行和字段編號從 0 開始。
int PQgetlength(const PGresult *res,
int row_number,
int column_number);這是特定數值的實際數據長度,也就是說,PQgetvalue 指向的對象的大小。 對于文本數據格式,它和 strlen() 相同。對于二進制格式,這是潛在的信息。 請注意我們不應該依靠 PQfsize 獲取實際數據長度。
向指定的輸出流打印所有的行和(可選的)字段名稱。
void PQprint(FILE* fout, /* 輸出流 */
const PGresult *res,
const PQprintOpt *po);
struct {
pqbool header; /* 打印輸出域頭和行計數 */
pqbool align; /* 填充對齊各字段 */
pqbool standard; /* 舊的傻格式 */
pqbool html3; /* 輸出 HTML 表 */
pqbool expanded; /* 擴展表 */
pqbool pager; /* 必要時在輸出中使用分頁器 */
char *fieldSep; /* 字段分隔符 */
char *tableOpt; /* 在 HTML 中插入 table ... */
char *caption; /* HTML caption */
char **fieldName; /* 替換字段名組成的空零結尾的數組 */
} PQprintOpt;這個函數以前被 psql 用于打印查詢結果,但是現在已經不用這個函數了。請注意它假設所有的數據都是文本格式。
這些函數用于從 PGresult 對象裡檢索那些非 SELECT 結果的信息。
返回產生PGresult的 SQL 命令的命令狀態字符串。
char * PQcmdStatus(PGresult *res);
通常這只是命令的名字,但是它可能包括額外的數據,比如處理過的行數。
返回被 SQL 命令影響的行的數量。
char * PQcmdTuples(PGresult *res);
如果產生PGresult的SQL 命令是 INSERT,UPDATE 或 DELETE,MOVE,或者 FETCH, 那麼這裡返回涉及行的行數。如果是其他命令返回一個空字符串。
返回一個插入的元組的對象標識(OID)── 如果SQL 命令是INSERT,而且剛好向帶 OID 的表插入了一行。否則,返回 InvalidOid。
Oid PQoidValue(const PGresult *res);
如果 SQL 命令是INSERT, 返回一個被插入的元組的對象ID的字串。 (如果 INSERT 並非恰好插入一行,或者目標表沒有OID,那麼字串將是 0。) 如果命令不是INSERT,則返回一個空字串。
char * PQoidStatus(const PGresult *res);
這個函數已經廢棄樂,因為有了 PQoidValue,而且它也不是線程安全的。
PQescapeString為在 SQL 命令中使用字串而對之進行逃逸處理。 在我們向 SQL 命令裡把數據值當作文本常量插入的時候很有用。有些字符(比如單引號和反斜槓)必須被逃逸, 以避免他們被 SQL 分析器作為特殊字符解析。
提示: 如果我們從一個不可信的來源收到一個字串的話,那麼做恰當的逃逸就更重要了。 否則就有安全性危險:你會收到"SQL 注射"攻擊,這個時候會有你不想看到的 SQL 喂給你的數據庫。
請注意,如果一個數據值是作為 PQexecParams 或者同族函數的一個獨立參數傳遞的, 那麼逃逸就既不必要,也不正確。
size_t PQescapeString (char *to, const char *from, size_t length);
參數 from 指向將要逃逸的字串的第一個字符, length 參數給出在這個字串裡的字符數量。字串結尾的字節零不是必須的,也不計入 length。 (如果在處理 length 個字節之前出現了一個字節零, 那麼 PQescapeString 在這個字節零處停止; 這個行為類似 strncpy。) to 應該指向一個緩衝區,這個緩衝區至少能保存 length 數值的兩倍還多一個的字符,否則該函數行為將不可預測。 調用 PQescapeString 就會把逃逸的 from 字串轉換到 to 緩衝區,把特殊字符以免它們導致任何問題, 並且追加終止的字節零。那些必須包圍在PostgreSQL 字串文本週圍的單引號不算結果字串的一部分;你應該在把單引號放在插入這個處理結果的SQL命令週圍。
PQescapeString 返回寫到 to 裡面的字符數目, 不包括結尾的字節零。
如果 to 和 from 字串相互重疊,那麼其行為不可預測。
逃逸那些在 SQL 命令中使用的用 bytea 表示的二進制數據。 和 PQescapeString 一樣,這個函數只有在直接向 SQL 字串插入數據的時候使用。
unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
在 SQL 語句中用做 bytea 字串文本的一部分的時候, 有些字節值必需逃逸(但是對于所有字節而言是可以逃逸)。 通常,要逃逸一個字節,它是被轉換成一個三位八進制數字, 該數字數值等于該字節的數值,然後前綴兩個反斜扛。 單引號(')和反斜扛字符(\)有自己特殊的逃逸序列。參閱 Section 8.4 獲取更多信息。 PQescapeBytea 執行這個操作,它只逃逸需要逃逸的最少的字符。
from 參數指向需要逃逸的字串的第一個字節, from_length 參數反映在這個二進制字串(結尾的字節零既不必要也不計算在內的字串)裡字節的個數。 to_length 參數應該是一個指向某個緩衝區的指針, 它的空間應該能夠保存逃逸後的結果字串長度。 結果字串長度不包括結果結尾的字節零。
PQescapeBytea 在內存重返回一個 from 參數的二進制字串的逃逸後的版本,這片內存是用 malloc() 分配的, 在結果不再需要的時候,必須用 PQfreemem() 釋放。 返回的字串已經把所有特殊的字符替換掉了,這樣他們就可以由 PostgreSQL的字串文本分析器以及 bytea 的輸入函數正確地處理。 同時還追加了一個結尾的字節零。那些必需包圍在 PostgreSQL字串文本週圍的單引號不算結果字串的一部分。
把一個二進制數據的逃逸後的字串表現形式轉換成二進制數據 --- PQescapeBytea 的反作用。 在以文本格式抽取 bytea 數據的時候是必須的, 但是在以二進制格式抽取的時候是不必要的。
unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
from 參數指向一個逃逸後的字串, 比如 PQgetvalue 處理過一個 bytea 字段後返回的。PQunescapeBytea 把它的字串表現形式轉換成二進制形式, 它返回一個用 malloc() 分配的指向該緩衝區的指針, 或者是出錯時返回空, 緩衝區的尺寸放在 to_length 裡。 在不再需要這個結果之後,這片內存必須用 PQfreemem() 釋放。
釋放 libpq 分配的內存。
void PQfreemem(void *ptr);
釋放由 libpq 分配的內存, 特別是 PQescapeBytea,PQunescapeBytea, 和 PQnotifies。這是 Microsoft Windows 必須的, 因為它不能跨越 DLL 釋放內存,除非使用了多線程的 DLL (VC6 中的 /MD)。 在其它平台上,這個函數和標準的庫函數free()一樣。