Click here to Skip to main content
15,891,687 members
Articles / Database Development / SQL Server
Article

SQL Server 2000 Collation Changer

Rate me:
Please Sign up or sign in to vote.
4.88/5 (99 votes)
3 Mar 2008CPOL4 min read 638.5K   10.1K   101   196
Change collation order for all text columns in a database

Introduction

Do you have an SQL application that you need to deploy in another country? Do you need to change the collation of your SQL database and all objects in it? If the answer is yes, then this could be a very slow process to do manually. If you run the alter database script as below:

SQL
ALTER DATABASE [My_Database] COLLATE My_Collation

You will find that the database default collation is changed for new columns, but all existing columns will retain the original collation order. Changing the collation on each column is a non-trivial task, as you need to drop all indexes, full text indexes and constraints associated with the column, along with any user-defined functions. Once the collation order has been changed, you can recreate the indexes, constraints and functions. This C# tool simplifies the process by creating an SQL script that does everything for you.

Using the Code

Simply run the program, select your SQL Server database and a new collation order. You have two options: you can either simply get the program to create an SQL script that you can run later (press the "Script Only" button) or you can actually make the changes (press the "Script and Execute" button). Things to note:

  • Always back up your database before running this tool. I cannot guarantee that you will not lose data. A number of the statements cannot be run in a transaction, so there is no way of detecting a failure and rolling back.
  • On SQL Server 2000, nText columns will be recreated so your column order will be slightly different.
  • To run the script, the program sets the database into single user mode to run the ALTER DATABASE [db_name] COLLATE [Collation Name] statement. You should therefore ensure that there are no open connections on the database before running the script (use the stored procedure SP_WHO to identify any open connections).
  • Since the script will drop and then rebuild all indexes and foreign keys in the database, you will find that it could take a long time to complete (possibly hours).
  • All columns will be changed to the new collation order, even if they have a non-default collation before running the script.
  • SQL 2005 support is gradually being added. If you encounter issues or missing functionality, please let me know.
  • If you change from a case-insensitive to a case-sensitive collation order, you may find errors occurring when recreating check constraints and functions. This is because your scripts will be parsed in a case-sensitive manner once the collation order has been changed. To work around this, I would recommend running the script in the program and reviewing the output once the script has run to completion. The error messages relating to each failure will be displayed in red under the code that failed.

Change History

18 January 2006

  • Original posting.

7 March 2006

  • Fixed bug where scripting failed on databases with case-sensitive collation orders. Script no longer drops foreign key constraints unless necessary.

30 August 2006

  • Fixed bug when scripting objects owned by different owners than the owner executing the script are used. May be seen as an error when scripting to #spindtab_____.
  • Fixed bug where scripting did not recreate permissions on table functions after they were recreated.

20 March 2007

  • Triggers now disabled while changes are made.
  • Altered sequence of execution to prevent errors following user feedback.
  • Added some SQL 2005 support. Let me know if you encounter any issues.
  • Resolved issue when recreating a table function where the body of a table function is greater than 4000 characters.
  • Reinstated the functionality to only delete the required indexes and primary keys.

10 October 2007

  • Added support for changing collation where full text indexes exist, including changing language used in the full text search.
  • Fixed issue when insteadof triggers exist on views.
  • Fixed issue where nText columns end up allowing nulls when they were originally declared NOT NULL.
  • SQL 2005 allows collation order of nText columns to be modified. The script has been modified to reflect this new functionality.
  • Fixed issues encountered when user-defined data types are used.
  • Added additional SQL 2005 support, including refactoring scripting logic to allow various parts of the script to be customised for different versions of SQL server. If you need to debug or customise the scripts, it should be a little easier to understand.
  • Converted from VB.NET to C#, as I use C# at work all the time and it is more familiar to me.
  • Moved execution task to a worker thread to give a more responsive UI.
  • Fixed issues when system databases have case-sensitive sort order.

1 March 2008

  • Created new code for handling indexes, statistics and relationships in SQL 2005. This new code uses the 2005 schema views and adds scripting support for new SQL 2005 functionality, such as included columns in non-clustered indexes.
  • Fixed issues where ANSI_NULLS setting is not correct after recreation of table functions.
  • Various minor UI bugs fixed.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer RXP Services
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralFull text search problems Pin
Per Otto5-Sep-06 3:40
Per Otto5-Sep-06 3:40 
Generalsql server 2005 compability, please... Pin
Per Otto3-Sep-06 22:36
Per Otto3-Sep-06 22:36 
GeneralRe: sql server 2005 compability, please... Pin
Alex Baker3-Sep-06 22:55
Alex Baker3-Sep-06 22:55 
GeneralRe: sql server 2005 compability, please... Pin
asperge15-Mar-07 3:45
asperge15-Mar-07 3:45 
GeneralRe: sql server 2005 compability, please... Pin
Alex Baker25-Mar-07 21:01
Alex Baker25-Mar-07 21:01 
GeneralTrigger Issue Resolution Pin
Shay Stowe31-Aug-06 4:18
Shay Stowe31-Aug-06 4:18 
Generalerror received Pin
bernieov23-Aug-06 7:48
bernieov23-Aug-06 7:48 
GeneralRe: error received Pin
Alex Baker24-Aug-06 23:28
Alex Baker24-Aug-06 23:28 
I see that there a couple of posts showing this issue. Could you run the following SQL script and send me a dump of the table created called __Test, extract to a text file or something like that and e-mail it to me at alexb at csl-uk.com.

could you also let me know the version of SQL server you are using

AND

using the query analyzer could you locate the stored procedure in the master database called sp_helpindex. If you right click on this item you will be given an option to script the stored procedure to a new window. Could you send me the code that this generates.

Many thanks




-- script drop of indexes - we will also populate a temp table that helps recreate the indexes later
create table __Test
(
objectname sysname collate database_default NULL,
index_name sysname collate database_default NULL,
stats int,
groupname sysname collate database_default NULL,
index_keys nvarchar(3000) collate database_default NULL, -- see @IX_keys above for length descr
OrigFillFactor tinyint,
IsAutoStatistic bit
)
go


--generate SQL to do indexes

declare @IX_indid smallint, -- the index id of an index
@IX_groupid smallint, -- the filegroup id of an index
@IX_indname sysname,
@IX_groupname sysname,
@IX_status int,
@IX_keys nvarchar(3000),
@IX_dbname sysname,
@IX_ObjID int,
@IX_ObjName sysname,
@IX_OrigFillFactor tinyint,
@IX_IsAutoStatistic bit

-- Check to see the the table exists and initialize @IX_objid.

-- OPEN CURSOR OVER INDEXES (skip stats: bug shiloh_51196)
declare ms_crs_ind cursor local static for
select id, object_name(id), indid, groupid, name, status, OrigFillFactor, case when (status & 64) = 0 then 0 else isnull(INDEXPROPERTY(id,name,'IsAutoStatistics'),0) end as IsAutoStatistic from sysindexes
where /*id = @IX_objid and */indid > 0 and indid < 255
and objectproperty(id,'ISMSSHIPPED')=0 and objectproperty(id,'IsTableFunction')=0
order by object_name(id),indid


open ms_crs_ind
fetch ms_crs_ind into @IX_objid, @IX_ObjName,@IX_indid, @IX_groupid, @IX_indname, @IX_status, @IX_OrigFillFactor, @IX_IsAutoStatistic


-- Now check out each index, figure out its type and keys and
-- save the info in a temporary table that we'll print out at the end.
while @@fetch_status >= 0
begin
-- First we'll figure out what the keys are.
declare @IX_i int, @IX_thiskey nvarchar(133) -- 128+5
declare @rebuild_index bit

select @IX_keys = '[' + index_col(@IX_objname, @IX_indid, 1)+']', @IX_i = 2, @rebuild_index=1 --parameter from application can force all to be rebuilt
if (indexkey_property(@IX_objid, @IX_indid, 1, 'IsDescending') = 1)
set @IX_keys = @IX_keys + ' DESC'

if (select collationid from syscolumns where id=@IX_objid and colid=indexkey_property(@IX_objid, @IX_indid, 1, 'columnid')) is not null
set @rebuild_index=1


set @IX_thiskey = '[' + index_col(@IX_objname, @IX_indid, @IX_i) + ']'
if ((@IX_thiskey is not null) and (indexkey_property(@IX_objid, @IX_indid, @IX_i, 'IsDescending') = 1))
set @IX_thiskey = @IX_thiskey + ' DESC'

if (select collationid from syscolumns where id=@IX_objid and colid=indexkey_property(@IX_objid, @IX_indid, @IX_i, 'columnid')) is not null
set @rebuild_index=1

while (@IX_thiskey is not null )
begin
select @IX_keys = @IX_keys + ', ' + @IX_thiskey, @IX_i = @IX_i + 1


if (select collationid from syscolumns where id=@IX_objid and colid=indexkey_property(@IX_objid, @IX_indid, @IX_i, 'columnid')) is not null
set @rebuild_index=1

set @IX_thiskey = '[' + index_col(@IX_objname, @IX_indid, @IX_i) + ']'
if ((@IX_thiskey is not null) and (indexkey_property(@IX_objid, @IX_indid, @IX_i, 'IsDescending') = 1))
select @IX_thiskey = @IX_thiskey + ' DESC'
end

select @IX_groupname = groupname from sysfilegroups where groupid = @IX_groupid

-- INSERT ROW FOR INDEX
if @rebuild_index =1
insert into __Test values (@IX_ObjName,@IX_indname, @IX_status, @IX_groupname, @IX_keys, @IX_OrigFillFactor, @IX_IsAutoStatistic)

-- Next index
fetch ms_crs_ind into @IX_objid, @IX_ObjName,@IX_indid, @IX_groupid, @IX_indname, @IX_status, @IX_OrigFillFactor, @IX_IsAutoStatistic
end
deallocate ms_crs_ind

select * from __Test



Alex Baker

GeneralKeep getting error about must declare variables Pin
tonywhite228-Jul-06 0:07
tonywhite228-Jul-06 0:07 
GeneralRe: Keep getting error about must declare variables Pin
tonywhite228-Jul-06 0:53
tonywhite228-Jul-06 0:53 
GeneralRe: Keep getting error about must declare variables Pin
Alex Baker30-Aug-06 3:23
Alex Baker30-Aug-06 3:23 
GeneralRe: Keep getting error about must declare variables Pin
tonywhite230-Aug-06 3:55
tonywhite230-Aug-06 3:55 
GeneralRe: Keep getting error about must declare variables Pin
tonywhite230-Aug-06 4:03
tonywhite230-Aug-06 4:03 
QuestionError when generating script Pin
Joe Seeley31-May-06 13:42
Joe Seeley31-May-06 13:42 
QuestionRe: Error when generating script Pin
cylar8-Jun-06 10:44
cylar8-Jun-06 10:44 
AnswerRe: Error when generating script Pin
Alex Baker30-Aug-06 3:25
Alex Baker30-Aug-06 3:25 
QuestionViews Pin
nigel.rickerby26-Apr-06 12:16
nigel.rickerby26-Apr-06 12:16 
AnswerRe: Views Pin
Alex Baker26-Apr-06 22:46
Alex Baker26-Apr-06 22:46 
GeneralRe: Views Pin
nigel.rickerby27-Apr-06 10:50
nigel.rickerby27-Apr-06 10:50 
GeneralGreat job! Pin
vanco26-Mar-06 11:37
vanco26-Mar-06 11:37 
GeneralThank you Pin
US15623-Mar-06 9:36
US15623-Mar-06 9:36 
QuestionWhy drop int FK? Pin
MrDevIt6-Mar-06 5:26
MrDevIt6-Mar-06 5:26 
AnswerRe: Why drop int FK? Pin
Alex Baker6-Mar-06 22:26
Alex Baker6-Mar-06 22:26 
AnswerRe: Why drop int FK? Pin
Alex Baker6-Mar-06 22:29
Alex Baker6-Mar-06 22:29 
GeneralGreat post - thank you Pin
MillieMoo22-Feb-06 5:49
MillieMoo22-Feb-06 5:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.