<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mauro Dalfreddo &#187; Migrazione</title>
	<atom:link href="http://www.maurodalfreddo.it/archives/tag/migrazione/feed" rel="self" type="application/rss+xml" />
	<link>http://www.maurodalfreddo.it</link>
	<description>My work, my life... my Blog</description>
	<lastBuildDate>Thu, 24 Jun 2010 12:10:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Migrare un database modificando la collation</title>
		<link>http://www.maurodalfreddo.it/archives/57/migrare-un-database-modificando-la-collation</link>
		<comments>http://www.maurodalfreddo.it/archives/57/migrare-un-database-modificando-la-collation#comments</comments>
		<pubDate>Tue, 20 May 2008 19:51:58 +0000</pubDate>
		<dc:creator>Mauro Dalfreddo</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Collation]]></category>
		<category><![CDATA[Migrazione]]></category>

		<guid isPermaLink="false">http://www.maurodalfreddo.it/?p=57</guid>
		<description><![CDATA[Come affrontare l'annoso problema di modificare la collation ad un database SQL Server]]></description>
			<content:encoded><![CDATA[<p>Mi sono dedicato ultimamente alla migrazione di alcuni database da un&#8217;istanza di SQL Server 2005 ad un&#8217;altra; come spesso succede, mi sono trovato di fronte al tedioso <strong>problema del cambiamento di collation</strong>, nel caso specifico da SQL_Latin1_General_CP1_CI_AS al Latin1_General_CI_AS. Se si utilizzano le funzionalità di backup e restore del database sulla nuova istanza, purtroppo ci si porta dietro la vecchia collation.</p>
<p>Esistono in internet degli script (ne viene riportato sotto uno stralcio) che modificano la collation degli oggetti contenuti nel DB (tabelle, colonne, viste, ecc.) e infine quella del DB stesso (utilizzando iterativamente dapprima <em>ALTER TABLE tablename ALTER COLUMN columnname COLLATE default</em>, ed infine <em>ALTER DATABASE databasename COLLATE default</em>). Funzionano in casi semplici, ma ci sono seri problemi quando la struttura del DB non è banale, ovvero sono presenti anche oggetti complessi (funzioni, foreign keys, trigger, indici, librerie, ecc. con le relative dipendenze), che devono essere droppati e ricreati.</p>
<p>La soluzione più semplice per migrare un database senza mantenere la collation originale da SERVER1 a SERVER2 è quella che descrivo nel seguito; i passi sono 3:</p>
<ol>
<li>scriptare il DB (e tutti gli oggetti contenuti) senza generare le collation sulla prima istanza.</li>
<li>eseguire tale script sulla seconda istanza</li>
<li>esportare ed importare i dati di tutte le tabelle con l&#8217;utility BCP</li>
</ol>
<p>I primi due passi sono banali. Per automatizzare il terzo, ho sviluppato il seguente script: in funzione del database MyDatabase scelto, l&#8217;obiettivo è quello di generate tutte le istruzioni BCP, una per ogni tabella (nel relativo schema) con i corretti parametri.</p>
<pre>use MyDatabase
DECLARE @srv_source varchar(50)
DECLARE @srv_destination varchar(50)
DECLARE @dbname varchar(50)
DECLARE @tmp varchar(max)
SELECT @dbname = db_name(), @tmp =char(13)+char(10),
           @srv_source = 'SERVER1', @srv_destination = 'SERVER2'</pre>
<pre>select @tmp = @tmp + 'bcp '+@dbname+'.'+schema_name(so.schema_id)+ '.'+so.name +
' out '+so.name+'.dat -c -T -q -S '+ @srv_source + char(13)+char(10) +
'bcp '+@dbname+'.'+schema_name(so.schema_id)+ '.'+so.name +
' in '+so.name+'.dat -c -T -E -q -S '+ @srv_destination + char(13)+char(10)
from sys.objects so where so.type ='U'</pre>
<pre>SELECT  1 AS TAG, 0 AS PARENT, @tmp
            as [SqlCommand!1!!cdata]
FOR XML
EXPLICIT, xmldata</pre>
<p><span id="more-57"></span></p>
<ul>
<li>Sostituire MyDatabase col nome del database effettivo.</li>
<li>Eseguire lo script col Management Studio: viene prodotto come unico risultato un campo XML; al suo interno, internamente al tag &lt;SqlCommand&gt; si troveranno tutte le istruzioni BCP.</li>
<li>Inserire tali istruzioni in un file .cmd (es. migrazione.cmd) appena creato. Spostare il file su SERVER2.</li>
<li>Eseguire il batch con un&#8217;utenza Windows avente opportuni diritti  sui database di entrambe le istanze SQL Server. Nel caso si voglia utilizzare l&#8217;autenticazione SQL, basta sostituire nello script il parametro &#8220;-T&#8221; con le opzioni &#8220;-U login -P password&#8221;</li>
</ul>
<p>Per esempio eseguendo lo script TSQL, viene generato il seguente output:</p>
<pre><span style="color: #339966;">&lt;Schema name="Schema1" xmlns="urn:schemas-microsoft-com:xml-data" </span>
<span style="color: #339966;">xmlns:dt="urn:schemas-microsoft-com:datatypes"&gt;
  &lt;ElementType name="SqlCommand" content="mixed" model="open"&gt;&lt;/ElementType&gt;
&lt;/Schema&gt;
&lt;SqlCommand xmlns="x-schema:#Schema1"&gt;&lt;![CDATA[
bcp MYDATABASE.dbo.Software out Software.dat -c -T -q -S SERVER1
bcp MYDATABASE.dbo.Software in Software.dat -c -T -E -q -S SERVER2

bcp MYDATABASE.dbo.Ambiti out Ambiti.dat -c -T -q -S SERVER1
bcp MYDATABASE.dbo.Ambiti in Ambiti.dat -c -T -E -q -S SERVER2
bcp MYDATABASE.dbo.Fornitori out Fornitori.dat -c -T -q -S SERVER1
bcp MYDATABASE.dbo.Fornitori in Fornitori.dat -c -T -E -q -S SERVER2
]]&gt;&lt;/SqlCommand&gt;
</span></pre>
<p><strong>Nota</strong>: l&#8217;utility BCP viene qui utilizzata per esportare i dati in file plain/text. Nella fase di importazione i valori dei campi identity vengono mantenuti (-E) e il relativo seme viene riallineato correttamente; i check constraints, i triggers, le foreign keys, nella fase di importazione vengono temporaneamente disabilitati (per default)</p>
<p>Giusto per soddisfare la curiosità, riporto un breve script utilizzato per generare le istruzioni TSQL per modificare le collation di tutte le colonne di tutte le tabelle.</p>
<pre><span style="color: #339966;">USE MyDatabase
GO
SET NOCOUNT ON
/*Find database default*/
DECLARE @name sysname,
@Collate VARCHAR(50)
SET @name =DB_NAME(7)
-- These props only available if db not shutdown
SET @Collate =
(SELECT CONVERT (sysname, DATABASEPROPERTYEX (@name,'Collation')))
SELECT 'ALTER TABLE '+ TABLE_NAME +' ALTER COLUMN '+ COLUMN_NAME
+' '+ DATA_TYPE +'('+CAST(CHARACTER_MAXIMUM_LENGTH ASVARCHAR(10))+') '
+'COLLATE '+ @Collate +  (
CASE IS_NULLABLE
WHEN 'NO' THEN' NOT NULL'
WHEN 'YES' THEN' NULL'
END
)
FROM INFORMATION_SCHEMA.columns
WHERE TABLE_NAME &lt;&gt;'dtproperties'
AND COLLATION_NAME NOT LIKE @Collate
ORDER BY COLUMN_NAME</span></pre>
<p> </p>
<p> </p>
<p>Riferimenti:</p>
<p><a href="http://support.microsoft.com/kb/325335/en-us" target="_blank">http://support.microsoft.com/kb/325335/en-us</a></p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms162802.aspx">http://msdn.microsoft.com/en-us/library/ms162802.aspx</a></p>
<p><a href="http://www.sqlserverspecialists.co.uk/blog/_archives/2007/10/31/3326039.html">http://www.sqlserverspecialists.co.uk/blog/_archives/2007/10/31/3326039.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.maurodalfreddo.it/archives/57/migrare-un-database-modificando-la-collation/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
