如何確保 SQL 腳本使用 ANSI 編碼執行?
也許這是一個愚蠢的問題,或者我以錯誤的方式問它。
我如何確定一個腳本(有數千行)正在使用 ANSI 編碼執行?
假設我們使用 Notepad++ 創建了一個腳本(程序員同時為 SQL 和 ORACLE 編寫程式碼),然後我們使用Encode in ANSI保存它:
好的。然後,我們的腳本中有一個
Â
字元。如果我們的客戶只是將此腳本複製到使用不同編碼的某個工具中(真的,我不知道為什麼,但有些使用者這樣做,我確定這不是為了查找錯誤),這Â
將被轉換為: ,但是由於我們的腳本有數千行,所以在客戶端沒有人會注意到這一點。我們知道使用者看不到這一點,他們不會閱讀整個腳本以確保一切正常。即使是為此付費的 DBA,也不會這樣做(我是一名 DBA,我肯定會一直閱讀所有腳本)。
那麼,我怎麼能確定,當使用者按下 時
F5
,所有腳本都用 ANSI 編碼,就像我們發送它的方式一樣,沒有這些奇怪的字元?我們只能通過正確的數據庫整理來實現這一點嗎?我試圖在腳本的第一行使用
case when asci character = the ascii(character) then ok else ERROR
(使用 ascii 進行測試)來考慮這樣的事情:Select CHAR(ASCII('ã')) As Teste_CHAR, CHAR(227) as Teste_CHAR_ASCII
所羅門,這是查詢:
Select *, Case When Teste_CHAR=Teste_CHAR_ASCII Then 'OK' Else 'Erro' END as STATUS_TESTE, Case When Teste_CHAR=Teste_CHAR_ASCII Then 'Everything is OK' Else 'Script will not run. your encode is different from ours' END as Mensagem_TESTE from ( Select CHAR(ASCII('ã')) As Teste_CHAR, CHAR(227) as Teste_CHAR_ASCII ) A
那麼,我怎麼能確定,當使用者按下 F5 時,所有腳本都使用 ANSI 編碼,就像我們發送它的方式一樣,沒有這些奇怪的字元?
你不能確定。不幸的是,這只是文本編碼的複雜性,尤其是非 Unicode 編碼。一切都只是字節。我們在螢幕上看到的只是這些字節的解釋。對於相同的字節或字節序列(取決於編碼),一種編碼肯定會顯示與另一種編碼不同的“字元”,但從技術上講,字節是字節並且所有字節都是有效的。
在 的情況下
Â
,您無法檢測到差異,因為沒有差異。您只能xC2
在 Notepad++ 中看到 ,因為這是該字元的字節值,但它本身不是有效的 UTF-8 或 UTF-16 / UCS-2 字節序列,因此 Notepad++ 僅向您顯示字節本身。現在,通過查找不在任何 8 位程式碼頁中的字元並將其與
?
/CHAR(63)
,如果它們匹配,則您不再使用 Unicode 編碼。這裡的缺陷是 8 位編碼無法指示它們是什麼編碼/程式碼頁。你只需要知道。但是,Unicode 編碼可以選擇在文件開頭放置幾個字節來指示正在使用的編碼類型。此字節序列稱為字節順序標記 (BOM),如果編碼正確,則將不可見。
因此,最好的選擇是使用其中一種 Unicode 編碼,並確保使用字節順序標記 (BOM) 保存文件,因為您通常可以選擇使用或不使用 BOM 的 Unicode 編碼進行保存。在 Notepad++(我使用)中,兩個 UCS-2 選項都是 BOM-only,但 UTF-8 可以選擇。如果您的腳本目前使用 ANSI,則在Notepad++的“**編碼”菜單中,選擇“**轉換為 UTF-8-BOM ”,然後保存文件。然後,當複制並粘貼到 SSMS 中時,一切都應該沒問題。在大多數編輯器中打開該文件會自動檢測到它被編碼為 UTF-8,因為 BOM 就在那裡。
我們只能通過正確的數據庫整理來實現這一點嗎?
這與 SQL Server 無關。這與客戶端工具及其使用的編碼有關。SSMS 幾乎可以肯定使用 UTF-16 LE(小端序),因為這是 Windows / SQL Server / .NET 使用的。
關於最近添加到問題末尾的查詢:
的
ã
值為0xE3
ANSI 編碼,在 UTF-8 或 UTF-16 中無效。在 Notepad++ 中,將編碼更改為 UTF-8(使用“Encode in”,而不是“Convert to”)會導致它只顯示xE3
. 將該版本的查詢複製並粘貼到 SSMS 中會獲取該字節加上下一個字節(用於結束的那個'
),並將其轉換為㧩
由於沒有結束引號而中斷查詢的字節。您可以通過在之後添加 2 個空格來解決此問題,ã
如下所示:CHAR(ASCII('ã '))
當編碼未更改時,這仍然可以按預期工作,因為該
ASCII
函式僅返回第一個字元的值,而其他字元(2 個空格)被忽略。如果將該腳本導入或更改為 UTF-8,它將在 Notepad++ 中顯示如下:
CHAR(ASCII('xE3 '))
那
xE3
將是一個“字元”。將該版本的查詢複製並粘貼到 SSMS 中將顯示如下:CHAR(ASCII('㠠'))
執行它會產生所需的“錯誤”結果。
**但是,**請注意,這不是一個萬無一失/有保證的測試。它主要只是表明腳本被錯誤地打開為 UTF-8、UTF-16 或不包含該
ã
字元的 8 位程式碼頁。如果腳本以非 ANSI 但仍包含字元的 8 位編碼打開,並且可能會誤解(即更改)其他字元,則此方法不會指示錯誤。
ã
保證 ANSI 編碼的唯一方法是查找 a) 在任何其他 8 位程式碼頁中不可用的字元,並且b) 在 UTF-8 或 UTF-16 中不一樣的字元。我不知道有任何這樣的字元,儘管我也沒有根據所有可用的程式碼頁檢查它們。
但是,如果您只處理以 UTF-8 格式打開文件的人,那麼進行上述調整應該適用於這種情況。