1

最初我有一个partner_email类型为 () 的列varchar。现在最近发生了一个变化,需要将其更改为XML数据类型,但需要将现有行转换为新列。

需要帮助

4

1 回答 1

1

单步执行脚本将有助于理解问题:

脚本 1

  1. 使用测试数据库
  2. 如果partner_email_tempPartner 表中不存在该列,则添加partner_email_temp为 XML 列
  3. 更新合作伙伴表。将 的值更改为partner_email_tempXML 友好的字符串版本partner_email。然后将其转换为 XML。使用 REPLACE 将所有 & 转换为编码的 &
  4. partner_email从合作伙伴中删除列
  5. 将列重命名partner_email_temppartner_email

所有这些都是第一次工作。当您第二次运行该脚本时,SQL Server 会进入第 2 步并再次执行 ALTER TABLE 语句。这是因为该列partner_email_temp不存在(它在第一次运行时被重命名为 partner_email)。

现在在第 3 步中,您正在尝试partner_email再次更新该列。问题是这个列现在是一个 XML 数据类型并且你的使用REPLACE是非法的。所以 SQL Server 会抛出一个错误。

脚本 2

  1. partner_email捕获Partner 中列的列数据类型。
  2. 如果列数据类型是 varchar(表示这是脚本的第一遍),执行 BEGIN 和 END 中的代码
  3. 如果该列partner_email_temp不存在,则将该 partner_email_temp列添加为 XML
  4. 通过将 的值更改为partner_email_temp XML 友好的字符串版本来更新合作伙伴表partner_email,然后将其转换为 XML。用于REPLACE将所有 & 转换为编码的 &
  5. partner_email从合作伙伴中删除列
  6. 将列重命名partner_email_temppartner_email

第二个脚本中的问题是您不能GO在 BEGIN 和 END 语句中使用该语句。

根据BOL

SQL Server 实用程序将 GO 解释为它们应该将当前批次的 Transact-SQL 语句发送到 SQL Server 实例的信号。

因此,在脚本 2 中,当 SQL Server 尝试编译时,它会注意到该列partner_email_temp不存在。它适用于脚本 1,因为这些部分是单独执行的。并且当执行引用的部分时partner_email_temp,该列确实存在。

那么如何解决呢?

如果您只需将partner_email列中的数据更新为正确的格式,然后将该列转换为 XML 数据类型,您实际上可以绕过所有列的删除和重命名。这可以在一个 SQL 批处理语句中实现,但您需要将其作为动态 SQL 执行,以便 SQL Server 仅在 varchar 数据类型REPLACE时尝试执行该语句: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, ''&'', ''&amp;'') 
  + ''</Email><Email></Email><Email></Email></PartnerEmails>'';
  ALTER TABLE Partner ALTER Column partner_email XML
  '

  EXEC (@sqlCmd) 

END
于 2012-06-10T03:45:47.770 回答