如何將 Unicode 字元詳細插入 varchar 數據庫?
我需要將此字元“●”插入到
VARCHAR
MSSQL 數據庫的列中,並將排序規則設置為SQL_Latin1_General_CP1_CI_AS
(或至少模擬我的 Python + Windows MSSQL 驅動程序可能已經完成的操作)。我試圖從我的客戶那裡插入它,但它被插入為?
.在 Python 中檢查的十六進制值
\xe2\x97\x8f
是二進制 226、151、143。排序規則說明 226 已定義,但 143 和 151 未定義。所以我最好是插入226?
我做這個練習的原因是我們的應用程序早先將這個字元插入到 DB 中。在這一點上,我不知道它是如何進入的,因為它通過一個帶有 Windows MSSQL 驅動程序的 Python 應用程序,我們的數據庫團隊編寫了一個腳本來糾正它,顯然它被替換為“?”。
現在我只是想重現這個場景來問他們為什麼它被替換為“?” 因為我們在應用程序中將其替換為空。由於我的應用程序已經修復了這個問題(我們刪除了任何大於 127 的內容),我試圖直接從後端模擬它以證明它正在被替換為“?” 這實際上是我的主張,我認為它已經完成,因為它在更新查詢中說“整理”。
UPDATE pr_response SET nur_respon = REPLACE (nur_respon, SUBSTRING(nur_respon, PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon), 1), '') WHERE PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon) > 0
這是刪除 Non-ASCII-Data > 127 的好腳本嗎?有人可以用簡單的英語解釋這個查詢嗎?
我需要將此字元“●”插入一
VARCHAR
列… 排序規則設置為SQL_Latin1_General_CP1_CI_AS
… 我做這個練習的原因是我們的應用程序早先將此字元插入數據庫。不,該應用程序沒有使用排序規則將此字元 ( Black Circle U+25CF ) 插入到
VARCHAR
列中[SQL_]Latin1_General...
。Latin1_General 排序規則使用程式碼頁 1252,它沒有這樣的字元,似乎也沒有“最合適”的映射將其轉換為類似的東西。該字元確實存在於某些程式碼頁中,例如韓語和日語排序規則使用的程式碼頁,如以下查詢所示(兩者都是雙字節字元集,這就是轉換為
VARBINARY
顯示兩個字節而不是一個字節的原因):SELECT CONVERT(VARCHAR(10), N'●' COLLATE Korean_100_CI_AS), CONVERT(VARBINARY(10), CONVERT(VARCHAR(10), N'●' COLLATE Korean_100_CI_AS)); -- ● 0xA1DC SELECT CONVERT(VARCHAR(10), N'●' COLLATE Japanese_XJIS_100_CI_AS), CONVERT(VARBINARY(10), CONVERT(VARCHAR(10), N'●' COLLATE Japanese_XJIS_100_CI_AS)); -- ● 0x819C SELECT CONVERT(VARCHAR(10), N'●' COLLATE Latin1_General_100_CI_AS), CONVERT(VARBINARY(10), CONVERT(VARCHAR(10), N'●' COLLATE Latin1_General_100_CI_AS)); -- ? 0x3F
但是,該應用程序可能插入了“•”(Bullet U+2022),它看起來非常相似,只是小了一點。“項目符號”字元在程式碼頁 1252(Dec 149 或十六進制 0x95)中可用。
我們的數據庫團隊編寫了一個腳本來糾正它,顯然它被替換為“?”
那麼,將“●”替換為“?” 聽起來不像修復它;-)。
現在我只是想重現這個場景來問他們為什麼它被替換為“?” 因為我們在應用程序中將其替換為空。由於我的應用程序已經解決了這個問題(我們刪除了任何大於 127 的內容)
不管技術細節如何,很明顯這兩個陳述不能同時為真:不能用“?”代替。並在訪問 SQL Server 之前被刪除。顯然,應用程式碼沒有對此進行修復,並且不會刪除值超過 127 的所有內容。它正在被轉換為“?” 在 SQL Server 中,因為正在插入該字元但在程式碼頁 1252 中不存在。
我認為它已經完成,因為它在更新查詢中顯示“COLLATE”。
不,通過
COLLATE
關鍵字強制二進制排序規則不會將此字元更改為“?”。列的排序規則 (SQL_Latin1_General_CP1_CI_AS
) 和顯式排序規則 (Latin1_General_BIN
) 都使用程式碼頁 1252,因此不會更改任何字元。“●”字元被替換為“?” 因為它被插入到
VARCHAR
列中。並且一旦它作為問號插入,就沒有什麼需要清理的了,也沒有辦法將該問號辨識為最初來自其他東西,而不是預期的問號。這是刪除 Non-ASCII-Data > 127 的好腳本嗎?有人可以用簡單的英語解釋這個查詢嗎?
該查詢查找任何出現的 ASCII 值大於 127 的字元(這就是它
PATINDEX
所做的),然後獲取任何這樣的字元(這就是它SUBSTRING
所做的),然後用空替換該列中該字元的所有出現字元串(這就是它的REPLACE
作用)。UPDATE
如果沒有找到 ASCII 值超過 127 的字元,則查詢不會執行任何操作。此查詢一次僅適用於一個字元。因此,如果一列有 2 個或多個 ASCII 值大於 127 的字元不是相同的 ASCII 值,則需要多次執行腳本。
在這種特殊情況下(即用“?”替換“●”),該查詢將無濟於事,因為該轉換正在進行中。該查詢僅處理 ASCII 值為 128 - 255 的字元,但“●”不是其中一個字元,因為它一開始就不可能出現在此列中。