Sql-Server

在處理實例/數據庫設置的不同排序規則時處理開發問題

  • January 27, 2021

在 sql server 中的不同排序規則上執行時,尋找一些關於我們如何處理腳本/模式的指導。

我們有一個創建多個儲存過程的過程,比如說模式銷售。因此,數據庫中所有相關的表和過程都儲存為sales.table1、sales.table2 …等,並儲存了諸如sales.us_proc1、sales.usp_proc2 …等的過程。

現在,對於具有預設排序規則的 SQL 伺服器實例上的數據庫的預設排序規則,procs 執行良好。但是,當我們在具有區分大小寫的排序規則實例的 sql server 上部署相同的對象/過程時,相同的腳本開始失敗。

到目前為止,我們可以做的是擁有 2 套腳本。對所有不區分大小寫的伺服器說第一個,對區分大小寫的其他集合說。

但問題是這兩組部署將在伺服器上進行,這會添加一堆不需要的對象/過程等。

請建議應該如何處理這樣的場景,無論伺服器/數據庫排序規則如何,都可以完成此類腳本的單組部署?

編輯- 嘗試更新我的問題以解決幾個問題:

在區分大小寫的數據庫上,腳本失敗並顯示如下錯誤消息 -

Msg207,Level 16, state1 - 無效的列名時間戳 - 比如說 proc1

Msg207,Level 16, state1 - 無效的列名 state- 說 proc2

是的,我們確實創建了 2 組腳本,這在理想情況下似乎沒有幫助,因為很多對像只是為區分大小寫的伺服器部署了兩次

此外,我們沒有創建數據庫,因為數據庫會在那裡,我們只需要部署一堆這些腳本。

此外,排序規則以 TempDB 和我們部署腳本的數據庫的 BIN 結尾。

正如 TempDB 的答案中所提到的,我已經完成了大部分腳本,看起來我們在大多數儲存過程中都沒有引用 #temp 表。但是,是的,我們確實使用局部變數和表變數@。這是否也適用於相同的問題?

將數據庫與實例排序規則隔離的最佳方法是使其成為Partially Contained Database,這將啟用Contained Database Collat​​ions

由於包含數據庫的設計目標是使它們自包含,因此必須切斷對實例和 tempdb 排序規則的依賴。為此,包含的數據庫引入了目錄排序規則的概念。目錄排序規則用於系統元數據和瞬態對象。詳情如下。

在包含的數據庫中,目錄排序規則 Latin1_General_100_CI_AS_WS_KS_SC。此排序規則對於 SQL Server 的所有實例上的所有包含的數據庫都是相同的,並且無法更改。

保留數據庫排序規則,但僅用作使用者數據的預設排序規則。預設情況下,數據庫排序規則等於模型數據庫排序規則,但使用者可以通過 CREATE 或 ALTER DATABASE 命令更改非包含數據庫。

模式與排序規則無關。此外,了解“腳本開始失敗”的含義肯定會有所幫助。請在問題中發布準確完整的錯誤消息。

目前,基於以下兩條資訊:

  1. 腳本失敗了,不僅僅是返回意外/更少的結果,

和: 2. 您說您可以擁有兩套腳本,而不是您已經擁有(或至少已經嘗試過)

我猜 procs 在大小寫方面對錶和/或模式名稱的引用不一致。例如,實際對像Sales.Table1在一個或多個 procs 中被引用為Sales.table1(唯一的區別是Table1中的****t)。這不是可以通過COLLATE查詢中的子句。這需要修復程式碼以使用正確的大小寫。事實上,如果您要部署到區分大小寫的實例,那麼最好更新您的開發(和測試/QA/Staging)實例,以便在數據庫級別也使用區分大小寫的預設排序規則。如果您的程式碼可以使用二進制排序規則部署在實例上,那麼也許可以使用二進制排序規則。這將幫助您在開發週期的早期擷取這些類型的錯誤。

此外,對數據庫使用區分大小寫甚至二進制排序規則(以_BIN2, not結尾_BIN)並將實例級排序規則保留為不區分大小寫(或與數據庫預設排序規則不同)將幫助您辨識查詢中的潛在錯誤與臨時表有關。

最後,您絕對不需要多組腳本來處理不同的排序規則,特別是如果這是由於在列名而不是表上使用不同的大小寫而導致創建過程失敗的問題(這會導致立即錯誤為它會找到表而不是列),或者如果表名的大小寫不同,則執行過程會出現問題,因為延遲名稱解析將允許創建 proc,但在執行時會出錯。

現在,關於臨時表,答案不一定是使用COLLATE DATABASE_DEFAULT. 這完全取決於您的應用程序試圖為每個受影響的字元串列完成什麼。(僅供參考:這部分是相同的,即使您部署完整的數據庫設置特定的排序規則並且執行在數據庫中使用任何隨機排序規則創建模式/對象的腳本沒有問題)。

如果任何受影響的列使用數據庫的預設排序規則(即未在語句中指定排序規則CREATE TABLE),並且應用程序不需要針對此特定操作/查詢的特定排序規則,那麼可以,COLLATE DATABASE_DEFAULT在每個謂詞/連接/引用旁邊使用在包含臨時表的查詢中。

但是,如果在創建表時為受影響的列提供了特定的排序規則,或者如果操作/查詢需要特定的排序規則(即無論如何都必須不區分大小寫的過濾器),那麼您應該COLLATE {specific_collation_name}在每個謂詞旁邊使用/concatenation/reference 在查詢中包含臨時表。

基於添加到問題的資訊:

這個場景和我根據之前的資訊猜測的差不多:

  1. 您的腳本正在部署到現有數據庫(您無法控制)
  2. 錯誤來自儲存過程中引用的列名,其大小寫與創建時不同。

因此,建議並沒有真正改變:您只需要一組腳本,其中列引用的集合與創建表時使用的大小寫匹配。因此,如果一個表有一個名為 的列TimeStamp,那麼Timestamp在程式碼中引用該列是一個錯誤(就像在許多/大多數程式語言中一樣)。你需要修復你的源程序,留下一個單一的、正確的腳本集,可以在任何地方工作。

您還應該考慮更改開發實例(或者至少只是數據庫,無論如何更容易更改)以使用二進制排序規則。或者,使用二進制排序規則部署到實例(或數據庫)作為 CI 流程的一部分(如果您有的話),或者如果您沒有自動化流程,則僅作為實踐問題。無論哪種情況,您都會在開發過程中更早地發現大小寫差異。

不使用臨時表將避免[tempdb]. 至於表變數,它們應該可以作為它們的字元串列,預設情況下,使用數據庫的預設排序規則。如果您將字元串列設置為與數據庫預設值不同的排序規則,並將其與未使用相同排序規則創建的表變數中的列進行比較,您仍然可能會遇到問題。在這種情況下,您只需COLLATE {collation_name}在發生問題的任何地方使用,指定用於使用者表中的列的排序規則。

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