Sql-Server

如何確保 SQL 腳本使用 ANSI 編碼執行?

  • November 9, 2017

也許這是一個愚蠢的問題,或者我以錯誤的方式問它。

我如何確定一個腳本(有數千行)正在使用 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 使用的。


關於最近添加到問題末尾的查詢:

ã值為0xE3ANSI 編碼,在 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 格式打開文件的人,那麼進行上述調整應該適用於這種情況。

引用自:https://dba.stackexchange.com/questions/190445