SQL, Analysis Services & related stories.

ALTER DATABASE ... ALTER COLLATION (FORCED).

As all of you know Microsoft has made a small problem for all SQL DBA and developers. If you have a database with any of SQL_xxxxx collations (for more details please have a look at the TERTIARY_WEIGHTS() function here), you will defenetily have a significant problem with index search and ordering performance if you'll try to upgrade your SQL Server with 2005 version. Some of developers was excited when first time reading this article, really :-).

Suddenly ALTER DATABASE .. ALTER COLLATION command will change database collation for you, but all objects will stay "as is" with old collation (by design). The only way to change collation for all existing objects is to create a new empty database with new desired collation and copy data into this new database (copy wizzard, for example).

To sort this issue out i created this small script (in attachment). It was tested both manually and with using VSTS DBPro, and i can confirm that you can change the collation of your database without any problem and manual work. As an input you should provide it with database with one collation, and as output you will have the same database with another (desired) collation. So as for me this is an analoque of ALTER DATABASE ... ALTER COLLATION FORCED command :-). How it works:

- you should use sqlcmd or SSMS in sqlcmd mode,

- specify database name as a parameter,

- specify desired collation as a parameter,

- run it and wait for results.

What is not covered by the script: table and index partitioning. I guess that if you are using these advanced options, you are smart enough to change this script to add required feature. Mostly i created this script for the following scenario: (1) detach database from SQL Server 6.5/7.0/200 version; (2) attach it to SQL Server 2005; (3) run this script; (4) use your database asap.

Some words about performance: than more tables with computed columns (computed column not at the end of the table) you have than more time you will have to wait. 100 Gigabyte db can be easily transformed within one hour on AI64 4way with EVA8000.

Also it is possible to use this script to study SQL 2005 system views and relationship between them.

Many thanks for any reply and comments.

 ---- January 2008

Many thanks to WaitForPete, script updated to fix these (and some other) issues.

Published Sunday, December 03, 2006 1:29 AM by Igor Kovalenko
Attachment(s): change_collation.sql

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

JohnGalt said:

Will this allow me to go through and reset the collation on every single field in the database to the database default??? It's killing me what SQL Server does changing fields randomly all of the time!

December 2, 2006 10:27 PM
 

Igor Kovalenko said:

Sure, JohnGalt. This script will go through every field in database and will change field collation. Even if this field is a member of primary constraint, has referensed by caclulated field, indexed, referensed by foreign key constraint.. whatever you want :-)

December 3, 2006 5:19 AM
 

Rod Weir said:

Hi Igor,

Thanks for a great script.  What a timesaver!

The script seems to have a problem scripting VarChar(MAX) columns.  The script ends up looking like this...

ALTER TABLE [dbo].[tblJobFinderSearch] ALTER COLUMN [ClientLink] varchar(-1) COLLATE DATABASE_DEFAULT  NULL

Notice the (-1) for the varchar setting?  This column used to be VarChar(Max).

Any ideas?

Thanks Rod.

March 22, 2007 5:57 PM
 

Rod Weir said:

Here's some other things to watch out for....

-- Make a backup of the database first!!!  If this script fails, it WILL leave the database in a half-repaired state where it may be missing all of the indexes, primary keys, constraints and other objects

-- Change any VarChar(MAX) columns back to VarChar(n) and then change back to MAX after running.

-- Remove any Full Text Catalogs before running this script

-- Run DBCC CHECKDB to identify any database errors or inconsistencies

-- Run DBCC UPDATEUSAGE(0) on database first, especially if the database has been upgraded from SQL Server 2000 to 2005

Thanks,

Rod

March 22, 2007 11:10 PM
 

Igor Kovalenko said:

Rod,

thanks a lot for your comment. We've identified issue with SQL Server collations during consolidation server process + migration from SQL 2000 to 2005 version. As far as SQL 2000 does not implement char(max) datatype these (any of max) datatypes are not covered by the script. You are absolutely right with Full Text Catalog feature - it might be usefull approach to drop and recreate all catalogues. Please also pay attention on partitioned tables and indexes - partitioning ans partitioned fuctions are also doesn't covered by the script. Hopefully you can use this script as a template to add any additional functions as you wish.

March 23, 2007 3:37 AM
 

Steeve Gauvreau said:

Do you have the same script but for SQL 2000

May 1, 2007 3:17 PM
 

Igor Kovalenko said:

No. It's to complicated for me because of lack of (n)varchar(max) data type. But you can try to look for AlterCollation.exe program (i saw this freeware tool with sources for SQL 2000). During testing i found a few bugs in it, but it is better then nothing.

May 1, 2007 3:33 PM
 

John Parker said:

Thanks a lot , saved me a fair bit of time.

Thought you should know there is a bug in the script if you are running it on a database which is already case sensitive from SSMS

The statement DECLARE cviews should be changed to DECLARE cViews

May 17, 2007 11:58 AM
 

Igor Kovalenko said:

John, thank you. I'll try to improve the script next time when i meet with case sensitive.

May 17, 2007 1:41 PM
 

Jaume Simon said:

Thank you, I downloaded your script and it ran flawlessly, everything seems to be ok and collated the same way.

November 30, 2007 12:04 PM
 

WaitForPete said:

Hi Igor

this script is most useful for our SQL 2005 customers who have fallen foul of this trap, but there is NO sign of the AlterCollation.exe program that you mentioned for SQL 2000.

I am having a look at porting the script back to 2000 but am floundering with the new system tables that you are using.

e.g. this clause crops up repeatedly

FROM sys.sql_modules m

JOIN sysobjects o on o.[objectid] = m.[objectid]

join sys.schemas s on s.schema_id = o.schema_id

WHERE (

m.uses_database_collation = 1

or

m.is_schema_bound = 1

)

but I haven't yet found a SQL 2000 equivalent for the uses_database_collation or is_schema_bound columns.

Obviously it would be far more efficient to locate the program, but right now the only search result that comes up is this one!  I did also look in the SQL 2000 media but it looks like that is not what you meant.

Any pointers most gratefully received.

Pete

December 18, 2007 11:51 AM
 

Igor Kovalenko said:

Pete,

Suddenly i don't have SQL 2000 nearby me, mostly SQL 2008 :-). I may firget something, but i think you can't find the analoque in SQL 2000. As for me it will be much easier to drop/recreate ALL stored procedures / functions / views instead of analysing column set. This will (1) simplify script (2) speedup processing.

Igor

December 18, 2007 1:36 PM
 

WaitForPete said:

I am allowed to drop support forSQL 2000 soon, in the meantime....

We have the drop and recreate script for all the programability objects anyway so it looks like sharp scissors time for that section.

Thanks

Pete

December 19, 2007 4:12 AM
 

WaitForPete said:

PS, I did find one bug on the way through.  The lines

IF @delete_referential_action = 1

SET @stmt = @stmt + ' NOT FOR REPLICATION'

, appearing in a couple of locations, are incorrect, they should be

IF @is_not_for_replication = 1

SET @stmt = @stmt + ' NOT FOR REPLICATION'

January 16, 2008 4:49 AM
 

David Punnett said:

GREAT SCRIPT!

Also -- I had to add a few lines:

Alter the order of the FK Constraints from: ON UPDATE CASCADE NOT FOR REPLICATION ON DELETE CASCADE  to   ON UPDATE CASCADE ON DELETE CASCADE NOT FOR REPLICATION  to avoid syntax problems.

Added:

, cc.is_not_for_replication

to

SELECT cc.[name]

, par_obj_name = o.[name]

, owner = s.[name]

, cc.definition

, [with_check] = case cc.is_not_trusted when 1 then 'WITH NOCHECK' else '' end

, cc.is_not_for_replication

FROM sys.check_constraints cc

join sys.objects o on o.[object_id] = cc.parent_object_id

join sys.schemas s on s.schema_id = o.schema_id

to get "NOT FOR REPLICATION" into the check constraints

Added:     SET @obj_def = CASE WHEN left(@obj_def, 1) = '(' THEN right(@obj_def, len(@obj_def) - 1) END

SET @obj_def = CASE WHEN right(@obj_def, 1) = ')' THEN left(@obj_def, len(@obj_def) - 1) END

to remove the double parenthesis that the default constraints get after the script.

Otherwise - GREAT SCRIPT!  

Thanks much!

David

January 24, 2008 5:06 PM
 

Bruno said:

Thank you for sharing your work Igor. This was a great timesaver!

April 3, 2008 2:41 PM
 

Evgenij said:

Hi,

the script does not work for me converting Lithuanian_CI_AS to Latin1_General_CI_AI

All Lithuanian letters look incorrect

Great pity.

Glad it worked for others.

Thanks for sharing, anyway.

April 10, 2008 5:05 PM
 

bnornes said:

I've tested the script on my CRM 3.0 datbase (backup). But the script fails on

ALTER TABLE [dbo].[fn_CollectForCascadeAssign] DROP CONSTRAINT [DF__fn_Collec__proce__5A8539BC]

Msg 4902, Level 16, State 1, Server PCSTEST1, Line 1

Cannot find the object "dbo.fn_CollectForCascadeAssign" because it does not exist or you do not have permissions.

-- DROP DEFAULT CONSTRAINT FAILED. SEE ERROR LOG FOR DETAILS.

Msg 50000, Level 16, State 1, Server PCSTEST1, Line 1245

It seems that the "Table-valued Functions" is deleted somewhere in the script.

If anyone could fix this problem I would be very thankful.

regards

bjorn

April 16, 2008 2:36 AM
 

Mark Dell said:

I have found that you can easily modify this script to support database names with strange characters in the name by replacing all of the instances of "$(destdb)" with "[$(destdb)]" (excluding the quotes of course) except for the use in the following query.  It should remain as shown here.

SELECT @RecoveryModel = recovery_model

FROM sys.databases

WHERE [name] = '$(destdb)'

May 9, 2008 4:52 PM
 

MDostie said:

Thanks a lot Igor.  Your really well done script saved my butt.

Only issue I had was a user defined fonction using a varchar(8000), changed it before running the script and all was fine.

With a database compare I also noticed an index drop a desc clause on a date field.

May 16, 2008 1:46 PM
 

Mjim said:

I see back in March 2007 Steeve Gauvreau asked if there was a SQL 2000 equivalent script.  Has anyone found such a script yet?

June 3, 2008 8:13 AM
 

kohmars said:

OMG - You rock! This was awesome, not so painful and complicated as I thought! I am no beginner with Sql Server but I am with 2005, so, I had some issues figuring out the sqlcmd, so incase anyone else needs a sample:

from dos prompt

sqlcmd -S your_server_name -U sa -P your_sa_password -i "change_collation.sql" -o "change_collation.out"

September 21, 2008 10:34 PM
 

Elias Suleiman said:

That is a great script. Thank you!

October 15, 2008 1:01 PM
 

matro said:

this saved me a lot of hours, really thank you for your work.

worked flawlessly on SQL Server 2005 SP2 64-Bit.

October 20, 2008 4:26 PM
 

Elias said:

Really nie.

Worked fine, except I got errors in the very last section of the script.

Msg 16916, Level 16, State 1, Line 3247

A cursor with the name 'cViews' does not exist.

Msg 16916, Level 16, State 1, Line 3253

A cursor with the name 'cViews' does not exist.

Msg 16916, Level 16, State 1, Line 3276

A cursor with the name 'cViews' does not exist.

Msg 16916, Level 16, State 1, Line 3277

A cursor with the name 'cViews' does not exist.

October 28, 2008 9:13 AM
 

Jie said:

This script worked great for me on SQL 2005 server and fixed the issue that I plan the big effort on othe way.

I really appreciate your work.

November 14, 2008 4:45 PM
 

PC said:

Great work. It is people like you that keep people like me in a job.

Cheers

February 5, 2009 10:44 AM
 

MC said:

Works flawlessly on my databases that have hundreds of columns with all sorts of constraints, etc. Thank you very much for saving me the trouble and time. Really appreciate your sharing this.

February 18, 2009 7:24 PM
 

JMG said:

Many thanks your script worked a treat on a database I'm migrating.

March 5, 2009 6:31 AM
 

Marco Alves said:

Terrific job. Congratulations.

Thx.

June 5, 2009 4:12 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

About Igor Kovalenko

I've been in IT since 1991 starting my carrier on Unix & C development. Now i am a consultant in Microsoft Services, Russia. My areas of experience - SQL & OLAP. I've been working with Microsoft tools for more than 15 years, started from asm 5.0 and Quick C 2.51 through (Visual) FoxPro, VB, C#... But my mission is SQL. Truly says i have enough knowledge both Oracle (8, 9.i) and Microsoft db technology, but it's to hard for me to cover both :-). My real data warehousing experience started with one of the largest DW implementation with using Oracle 9i in Russia till 2002. Of course i also implemented the first part of BI project on top of this DW with using SQL AS 2000 & Crystal reports. After that for a year i was a seniour developer, Online Services, in Dell UK, Bracknell (c++/vb/Oracle/SQL/ASP). In 2003 i was a little bit tired from High Technology World and decided to join Deloitte, Moscow, where i was a Finance analyst, member of Business Director Group. I really miss a half of my IT knowledge this time (SQL & Crystal is only useful), but now i perfectly know the "underground" of any BIG 4 consulting company, budgeting and managing process details, FTE, Utilization, OPTS analysis.... Hell, real accounting hell. I was excited to design and implement my first (and last) project with using Cognos EP tool. At the end of 2005 i was hired by my favorite company :-) Microsoft and now i am working with my favorite tool: SQL Server. To keep a long story short :-).

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker