int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ );
取得一個變更集,其中包含傳遞為第一個參數的 session 物件所附加表格的變更。如果成功,設定 *ppChangeset 指向一個包含變更集的緩衝區,並將 *pnChangeset 設定為變更集在回傳 SQLITE_OK 前的大小(以位元組為單位)。如果發生錯誤,將 *ppChangeset 和 *pnChangeset 都設定為零,並回傳一個 SQLite 錯誤碼。
變更集包含零個或多個 INSERT、UPDATE 和/或 DELETE 變更,每個變更代表一個附加表格單一列的變更。INSERT 變更包含新資料庫列每個欄位的數值。DELETE 包含已刪除資料庫列每個欄位的原始數值。UPDATE 變更包含已更新資料庫列每個欄位的原始數值,以及每個已更新非主鍵欄位的更新數值。UPDATE 變更無法表示修改主鍵欄位數值的變更。如果進行此類變更,它會在變更集中表示為 DELETE 後接 INSERT。
對於在一個或多個 PRIMARY KEY 欄位中儲存 NULL 值的列,不會記錄變更。如果此類列被插入或刪除,此函式回傳的變更集中不會有對應的變更。如果現有列在一個或多個 PRIMARY KEY 欄位中儲存 NULL 值,並更新為所有 PRIMARY KEY 欄位都為非 NULL,變更集中只會出現 INSERT。類似地,如果現有列具有非 NULL PRIMARY KEY 值,並更新為其一個或多個 PRIMARY KEY 欄位設定為 NULL,產生的變更集中只會包含 DELETE 變更。
變更集的內容可以使用透過 sqlite3changeset_start() API 建立的迭代器來遍歷。可以使用 sqlite3changeset_apply() API 將變更集套用至具有相容架構的資料庫。
在此函數產生的變更集中,與單一資料表相關的所有變更都會分組在一起。換句話說,在遍歷變更集或將變更集套用至資料庫時,與單一資料表相關的所有變更都會在處理下一個資料表之前處理完畢。資料表會依附加 (或自動附加) 至 sqlite3_session 物件的順序進行排序。與單一資料表相關的變更儲存順序未定義。
成功呼叫此函數後,呼叫者有責任最終使用 sqlite3_free() 釋放 *ppChangeset 指向的緩衝區。
資料表附加至工作階段物件後,工作階段物件會記錄插入至資料表的所有新列的主要金鑰值。它也會記錄任何已刪除或已更新列的原始主要金鑰和其他欄位值。對於每個唯一的主要金鑰值,資料只會記錄一次 - 在工作階段生命週期中,具有所述主要金鑰的第一列插入、更新或刪除時。
前一段落有一個例外:當列插入、更新或刪除時,如果其主要金鑰欄位中有一個或多個包含 NULL 值,則不會記錄變更。
因此,工作階段物件會累積兩種類型的記錄 - 僅包含主要金鑰值的記錄 (在使用者插入新記錄時建立) 和包含主要金鑰值和其它資料表欄位原始值的記錄 (在使用者刪除或更新記錄時建立)。
呼叫此函數時,會使用累積記錄和資料庫檔案的目前內容建立要求的變更集。具體來說
這表示,在其他事項中,如果一列已插入,然後在會話物件處於活動狀態時刪除,則變更組中不會出現插入或刪除。或者,如果一列已刪除,然後在會話物件處於非活動狀態時插入具有相同主鍵值的一列,則產生的變更組將包含 UPDATE 變更,而不是 DELETE 和 INSERT。
當會話物件已停用(請參閱 sqlite3session_enable() API)時,它不會在插入、更新或刪除列時累積記錄。如果在會話期間多次寫入單一列,這可能會產生一些違反直覺的效果。例如,如果在會話物件已啟用時插入一列,然後在同一個會話物件已停用時刪除,則變更組中不會出現 INSERT 記錄,即使刪除是在會話已停用時進行。或者,如果在會話已停用時更新一列的欄位,而在會話已啟用時更新同一列的另一個欄位,則產生的變更組將包含更新兩個欄位的 UPDATE 變更。