開發ERP數據維護工具之一 修改SQL Server數據庫排序規則 Change Collation


在部署ERP應用時,經常會碰到在開發環境下,沒有問題,部署到服務器上,就出錯。不同語言版本的操作系統、不同的數據庫版本,等等因素的數據庫排序規則的問題。比如在安裝SQL Server 時取默認的規則,中文環境下,會設置為Chinese_PRC_CI_AS,但我們需要的規則應該是SQL_Latin1_General_CP1_CI_AS。在數據操作過程中,這個不一致會導致SQL語句的字符串相等報錯。錯誤語句如下

The default collation of database 'pco' cannot be set to SQL_Latin1_General_CP1_CI_AS.

對於報表的存儲過程,錯誤更嚴重。每個有建立臨時表,比較字符串的地方,都會報錯。

當安裝時設定的SQL Server排序規則為Chinese_PRC_CI_AS,建數據庫時又選定為默認規則,則數據庫的排序規則也是Chinese_PRC_CI_AS,運行如下的腳本把它改變為SQL_Latin1_General_CP1_CI_AS:

Alter   database   [Database name]   collate   SQL_Latin1_General_CP1_CI_AS

當數據庫中的Index,Constraint依賴於數據庫排序規則時,上面的語句很難成功運行。

CodeProject上面有一篇文章Easy way to change collation of all database objects in SQL Server

這里的程序以依據這篇文章介紹的原理,開發出來對它封裝一下,簡化操作。

image

如圖所示的軟件界面,設定SQL Server實例,選取數據庫名字,輸入要改變成的排序規則,點擊處理,即可生成包含7個步驟運行的SQL語句,把這7個SQL語句依次放到數據庫中執行一次,即可改變它的排序規則。

1 Prepare Procedure 准備程序,先要運行一下,以生成創建SQL Server Constraint/Index的腳本。

有五個關鍵的存儲過程要先運行CreateKeyIndex.sql ,DropKeyIndex.sql,ScriptCreateTableKeys.sql,ScriptDropTableKeys.sql,G
enerateDefaultCollation.sql 。目的如它的名字所示,創建索引和約束。

在編程過程,原本是想把這幾個SQL語句直接以SqlCommand的方式發送到SQL Server中去運行,但是它會報一個SQL語句太長的錯誤,求助於Google沒有解決,只好在SQL Server服務器中手動運行這幾個腳本。

后面生成的SQL語句,也都應用此政策(policy),一方面是沒有解決SQL語句太長的問題,另一方面,從效率上來說,直接在SQL Server Management Studio中運行SQL語句的效率是最好的。

2 Drop Key Index 依據數據庫中的所有表刪除所有的Index,生成它如下的例子語句

DROP INDEX [PRCALW_INDEX2]
ON [dbo].[WorkCentreCalendar];


DROP INDEX [PRCALW_INDEX0]
ON [dbo].[WorkCentreCalendar];


ALTER TABLE [dbo].[WorkCentreCalendar]
DROP CONSTRAINT [PRCALW_PK];
 

3  Change Collation 改變表的排序規則 對字符串字段,它會生成ALTER語句,例子如下

ALTER TABLE [CalendarTemplate] ALTER COLUMN [REF_NO] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [FIRST_DAY] char(1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [FIRST_SHIFT_BEGIN] nchar(4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [SENCOND_SHIFT_BEGIN] nchar(4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [THIRD_SHIFT_BEGIN] nchar(4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [MON_HOLIDAY] char(1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [WEN_HOLIDAY] char(1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [CalendarTemplate] ALTER COLUMN [WEN_HALFDAY] char(1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL

4  Create Key Index 創建主鍵腳本,主要是表的主鍵,在這里重建,例子腳本如下

ALTER TABLE [dbo].[Account]
ADD CONSTRAINT [GBACCT_PK]
PRIMARY KEY CLUSTERED
( 
 [ACCT_NO]
)
WITH 
(
 PAD_INDEX = OFF,
 IGNORE_DUP_KEY = OFF,
 ALLOW_ROW_LOCKS = ON,
 ALLOW_PAGE_LOCKS = ON
) 
ON [PRIMARY];


CREATE UNIQUE NONCLUSTERED INDEX [GBACCT_INDEX0]
ON [dbo].[Account]
( 
 [RECNUM]
)
WITH 
(
 PAD_INDEX = OFF,
 FILLFACTOR = 70,
 IGNORE_DUP_KEY = OFF,
 ALLOW_ROW_LOCKS = ON,
 ALLOW_PAGE_LOCKS = ON
) 
ON [PRIMARY];


CREATE UNIQUE NONCLUSTERED INDEX [GBACCT_INDEX2]
ON [dbo].[Account]
( 
 [ACCT_NAME],
 [ACCT_NO]
)
WITH 
(
 PAD_INDEX = OFF,
 IGNORE_DUP_KEY = OFF,
 ALLOW_ROW_LOCKS = ON,
 ALLOW_PAGE_LOCKS = ON
) 
ON [PRIMARY];

5 Disable Check Constraint  把Check 約束禁用

 Declare @action nvarchar(20) 
 SET @action='Disable'  --Enable Disable
--Declare @action nvarchar(20)
--SET @action='Enable'

Declare @sql nvarchar(200)
Declare @Name nvarchar(200)
Declare @TableName nvarchar(200)
Declare Cur Cursor For SELECT name,OBJECT_NAME(parent_object_id) FROM sys.check_constraints
Open Cur
Fetch next From Cur Into @Name,@TableName
While @@fetch_status=0     
BEGIN
   IF @action='Disable'
     SELECT @sql='alter table ' + @TableName +' NOCHECK CONSTRAINT ' + @Name
   ELSE 
     SELECT @sql='alter table ' + @TableName +' WITH CHECK CHECK CONSTRAINT  ' + @Name
      
   Fetch Next From Cur Into @Name,@TableName
End   
Close Cur   
Deallocate Cur

 

6 Udpdate Database 這一步驟,看到期待的經典的語句

ALTER DATABASE MIS SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE MIS COLLATE  SQL_Latin1_General_CP1_CI_AS
ALTER DATABASE MIS SET ARITHABORT ON 
ALTER DATABASE MIS SET MULTI_USER 

7  Enable Check Constraint 啟用約束,完成數據庫的排序修改動作

 Declare @action nvarchar(20) 
 SET @action='Enable'  --Enable Disable
--Declare @action nvarchar(20)
--SET @action='Enable'

Declare @sql nvarchar(200)
Declare @Name nvarchar(200)
Declare @TableName nvarchar(200)
Declare Cur Cursor For SELECT name,OBJECT_NAME(parent_object_id) FROM sys.check_constraints
Open Cur
Fetch next From Cur Into @Name,@TableName
While @@fetch_status=0     
BEGIN
   IF @action='Disable'
     SELECT @sql='alter table ' + @TableName +' NOCHECK CONSTRAINT ' + @Name
   ELSE 
     SELECT @sql='alter table ' + @TableName +' WITH CHECK CHECK CONSTRAINT  ' + @Name
      
   Fetch Next From Cur Into @Name,@TableName
End   
Close Cur   
Deallocate Cur

第5步和第7步使用的SQL語句基本相同,遍歷所有的約束,生成NOCHECK和WITH CHECK的SQL語句。

您可以到CodeProject網站中下載源代碼,文章標題是

Easy way to change collation of all database objects in SQL Server。

剛開始讀這篇文章,有些吃力,消化不了。在Google尋找解決辦法過程中,最后還是覺得他提出的方案是很好的。在這里,我向前走一步,做一個固化的程序來解決問題,讓步驟明了簡明,著文以分享給大家,歡迎指正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM