對於無效的 UTF,SQLite 遵循垃圾進,垃圾出的政策 (GIGO)。如果您將無效的 UTF 插入 SQLite 資料庫,然後嘗試查詢該資料,您取回的資料可能與您輸入的資料不完全相同。如果您輸入垃圾,則您無法抱怨您取回的垃圾不同。
在這個討論中,「無效的 UTF」可能表示下列任何情況
UTF-16 中的無效代理對。
UTF-8 中的無效多位元組序列。
使用比表示單一碼點所需的更多 UTF-8 位元組。(範例:將 'A' 編碼為雙位元組序列 0xc1, 0x01,而不是僅使用單一 0x41 位元組。)
嵌入在字串中的 NUL 字元 (U+0000)。
無效的組合字元序列。
編碼未定義的 Unicode 字元的 UTF-8 或 UTF-16 位元組序列。
如果您將無效的 UTF 插入 SQLite 資料庫,SQLite 不保證您會取回什麼文字。但它保證無效的 UTF 永遠不會導致記憶體錯誤(陣列溢位、讀取或寫入未初始化的記憶體等),至少對於 SQLite 的內建處理而言。換句話說,無效的 UTF 不會導致 SQLite 崩潰。
此承諾僅適用於核心 SQLite 元件,當然不適用於應用程式提供的擴充功能。如果應用程式新增新的應用程式定義 SQL 函式或虛擬表格或排序序列或其他擴充功能,而資料庫包含無效的 UTF,則無效的 UTF 可能會傳遞到這些擴充功能中。如果無效的 UTF 導致其中一個擴充功能崩潰,那麼這是擴充功能的問題,而不是 SQLite 的問題。
SQLite 沒有嘗試強制執行 UTF 格式化規則。您可以將無效的 UTF 插入 TEXT 欄位,而 SQLite 也不會抱怨。它會盡可能儲存無效的 TEXT。SQLite 視其在世界上的角色為儲存引擎,而不是文字格式驗證引擎。
SQLite 沒有承諾總是保留無效的 UTF,但它確實做出了努力。一般來說,如果您將無效的 UTF 插入 SQLite,您將會取得完全相同的位元組序列,只要您沒有要求 SQLite 以任何方式轉換文字。
例如,如果您將一些具有無效代理項的 UTF-16LE 插入具有 PRAGMA 編碼=UTF16LE 的資料庫的表格的 TEXT 欄位,然後稍後使用 sqlite3_column_text16() 查詢該欄位,您可能會取得完全相同的無效 UTF-16。但是,如果您在 PRAGMA 編碼=UTF8 資料庫中插入相同的無效 UTF-16LE 內容,則在儲存時必須將內容轉換為 UTF8,這可能會對內容造成不可逆的變更。或者,如果您將相同的無效 UTF-16LE 內容插入 PRAGMA 編碼=UTF16LE 資料庫,但使用 sqlite3_column_text() 讀取它,則在讀取過程中必須進行 UTF16 到 UTF8 的轉換,而該轉換可能會造成不可逆的變更。
或者,假設您使用 UTF-8 執行所有操作(最常見的情況)。無效的 UTF-8 通常會在資料庫中傳遞,其位元組序列不會有任何變更。但是,如果您嘗試使用 SQL 函數(例如 substr() 或 replace())轉換無效的 UTF-8,或者如果您嘗試使用 LIKE 運算子進行字串比對,則可能會得到意外的結果。
因此,換句話說,SQLite 沒有積極嘗試顛覆您的無效文字。但是,當您要求 SQLite 轉換無效的 UTF 時,無法保證這些轉換是可逆的,甚至是合理的。
如果資料庫結構包含無效 UTF 的名稱(表格名稱、欄位名稱、索引名稱等),SQLite 將繼續正常運作。就 SQLite 而言,這些名稱只是位元組序列。SQLite 不在乎它們是否為有效的 UTF。
在產生錯誤訊息時(例如,使用 sqlite3_errmsg()),SQLite 有時會將資料庫結構的一部分嵌入錯誤訊息中。如果這些嵌入的結構元素是無效的 UTF,則產生的錯誤訊息也可能是無效的 UTF。類似地,PRAGMA integrity_check 和類似陳述式的輸出有時會嵌入結構元素的名稱。如果這些結構元素名稱是無效的 UTF,則指令的輸出也會是無效的 UTF。
此頁面最後修改於 2023-12-05 14:43:20 UTC