最初はpartner_email
、タイプが。の列()がありvarchar
ます。最近の変更により、データ型に変更するために変更する必要がありますXML
が、既存の行を新しい列に変換する必要があります。
必要なヘルプ
最初はpartner_email
、タイプが。の列()がありvarchar
ます。最近の変更により、データ型に変更するために変更する必要がありますXML
が、既存の行を新しい列に変換する必要があります。
必要なヘルプ
スクリプトをステップスルーすると、問題を理解するのに役立ちます。
スクリプト1
partner_email_temp
がPartnerテーブルに存在しない場合はpartner_email_temp
、XML列として追加しますpartner_email_temp
XML対応の文字列バージョンに変更しますpartner_email
。次に、それをXMLに変換します。REPLACEを使用して、すべての&をエンコードされた&ampに変換しますpartner_email
パートナーから列を削除しますpartner_email_temp
ますpartner_email
これはすべて初めて機能します。スクリプトを2回実行すると、SQL Serverはステップ2に進み、ALTERTABLEステートメントを再度実行します。これは、列partner_email_temp
が存在しないためです(最初の実行でpartner_emailに名前が変更されました)。
partner_email
ここで、ステップ3で、列を再度更新しようとしています。問題は、この列がXMLデータ型になり、使用REPLACE
が違法になることです。そのため、SQLServerはエラーをスローします。
スクリプト2
partner_email
Partnerの列の列データ型をキャプチャします。partner_email_temp
が存在しない場合は、
partner_email_temp
列をXMLとして追加しますpartner_email_temp
の値をXMLに適した文字列バージョンに変更してPartnerテーブルを更新してから、XMLpartner_email
に変換します。REPLACE
すべての&をエンコードされた&ampに変換するために使用しますpartner_email
パートナーから列を削除しますpartner_email_temp
ますpartner_email
GO
2番目のスクリプトの問題は、BEGINステートメントとENDステートメントでステートメントを使用できないことです。
BOLによると:
SQL Serverユーティリティは、GOを、Transact-SQLステートメントの現在のバッチをSQLServerのインスタンスに送信する必要があるというシグナルとして解釈します。
partner_email_temp
したがって、スクリプト2では、SQL Serverがコンパイルを試みると、列が存在しないことに気付きます。セクションが個別に実行されるため、スクリプト1で機能します。そして、参照する部分partner_email_temp
が実行されるとき、列は存在します。
では、どのように修正しますか?
partner_email
列のデータを正しい形式に更新してから、列をXMLデータ型に変換するだけで、実際には列の削除と名前変更をすべてバイパスできます。これは1つのSQLバッチステートメントで実現できますが、SQL Serverがvarcharデータ型のREPLACE
場合にのみステートメントを実行しようとするように、動的SQLとして実行する必要があります。partner_email column
IF NOT EXISTS
(
SELECT *
FROM INFORMATION_SCHEMA.columns
WHERE table_name = 'Partner'
AND column_name = 'partner_email'
AND data_type = 'xml'
)
BEGIN
DECLARE @sqlCmd NVARCHAR(4000)
SET @sqlCmd = N'
UPDATE [dbo].[Partner]
SET partner_email = ''<PartnerEmails><Email>''
+ REPLACE(partner_email, ''&'', ''&'')
+ ''</Email><Email></Email><Email></Email></PartnerEmails>'';
ALTER TABLE Partner ALTER Column partner_email XML
'
EXEC (@sqlCmd)
END