【问题标题】:SQL Server - script to update database columns from varchar to nvarchar if not already nvarcharSQL Server - 将数据库列从 varchar 更新为 nvarchar 的脚本(如果还没有 nvarchar)
【发布时间】:2010-09-15 20:25:42
【问题描述】:

我处于必须使用脚本将现有数据库结构从 varchar 更新为 nvarchar 的情况。由于每次运行配置应用程序时都会运行此脚本,因此我宁愿确定列是否已更改为 nvarchar 并且不对表执行更改。我必须支持的数据库是 SQL Server 2000、2005 和 2008。

【问题讨论】:

    标签: sql-server alter-table


    【解决方案1】:

    进一步更新以修复 MAX 被替换为 -1。

    SELECT cmd = 'ALTER TABLE [' + c.table_schema + '].[' + c.table_name 
     + '] ALTER COLUMN [' + c.column_name + '] NVARCHAR('
     +CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000 THEN 
     CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
     'MAX' ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) END ELSE 'MAX' END+')' 
     + CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END,*
    FROM information_schema.columns c
    WHERE c.data_type='VARCHAR' 
    ORDER BY CHARACTER_MAXIMUM_LENGTH DESC
    

    感谢Nezam's Answer

    另一个管理默认值:

    SELECT cmd = 
    CASE WHEN name IS NOT NULL THEN
        'ALTER TABLE ' + c.table_name + ' DROP CONSTRAINT ' + d.name + '; ' +
        'ALTER TABLE [' + c.table_schema + '].[' + c.table_name + '] ALTER COLUMN [' + c.column_name + '] ' + 
        'NVARCHAR(' +
        CASE WHEN CHARACTER_MAXIMUM_LENGTH <= 4000 THEN 
            CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
                'MAX' 
            ELSE 
                CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) 
            END 
         ELSE 
            'MAX' 
        END 
        + ')' +
        CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END + '; ' + 
        'ALTER TABLE '+ c.table_name + ' ADD CONSTRAINT ' + d.name +' DEFAULT '+ c.column_default + ' FOR ' + c.column_name + ';'
    ELSE
        'ALTER TABLE [' + c.table_schema + '].[' + c.table_name + '] ALTER COLUMN [' + c.column_name + '] ' +
        'NVARCHAR(' +
        CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000 THEN
            CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
                'MAX' 
            ELSE 
                CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) 
            END 
        ELSE 
            'MAX' 
        END
        + ')' +
        CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END 
    END,d.name, c.*
    FROM information_schema.columns c
    LEFT OUTER JOIN sys.default_constraints d ON d.parent_object_id = object_id(c.table_name)
    AND d.parent_column_id = columnproperty(object_id(c.table_name), c.column_name, 'ColumnId')
    WHERE c.data_type='VARCHAR' 
    ORDER BY CHARACTER_MAXIMUM_LENGTH DESC
    

    【讨论】:

      【解决方案2】:

      Josef 的答案的问题是它会在执行查询后将NOT NULL 字段更改为NULL。以下操作修复了它:

      SELECT cmd = 'alter table [' + c.table_schema + '].[' + c.table_name 
       + '] alter column [' + c.column_name + '] nvarchar('
       +CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000
             THEN CAST(CHARACTER_MAXIMUM_LENGTH as varchar(10)) ELSE 'max' END+')' 
       + CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END,*
      FROM information_schema.columns c
      WHERE c.data_type='varchar' 
      ORDER BY CHARACTER_MAXIMUM_LENGTH desc
      

      感谢Igor's answer

      【讨论】:

        【解决方案3】:

        修复空间问题并添加架构

        SELECT 'ALTER TABLE [' + isnull(schema_name(syo.object_id), sysc.name) + '].[' +  syo.name 
            + '] ALTER COLUMN ' + syc.name + ' NVARCHAR(' + case syc.max_length when -1 then 'MAX' 
                ELSE convert(nvarchar(10),syc.max_length) end + ');'
           FROM sys.objects syo
           JOIN sys.columns syc ON
             syc.object_id= syo.object_id
           JOIN sys.types syt ON
             syt.system_type_id = syc.system_type_id
            JOIN sys.schemas sysc ON
            syo.schema_id=sysc.schema_id
           WHERE 
             syt.name = 'varchar' 
            and syo.type='U'
        

        【讨论】:

          【解决方案4】:

          您可以运行以下脚本,该脚本将为您提供一组 ALTER 命令:

          SELECT 'ALTER TABLE ' + isnull(schema_name(syo.id), 'dbo') + '.' +  syo.name 
              + ' ALTER COLUMN ' + syc.name + ' NVARCHAR(' + case syc.length when -1 then 'MAX' 
                  ELSE convert(nvarchar(10),syc.length) end + ');'
             FROM sysobjects syo
             JOIN syscolumns syc ON
               syc.id = syo.id
             JOIN systypes syt ON
               syt.xtype = syc.xtype
             WHERE 
               syt.name = 'varchar' 
              and syo.xtype='U'
          

          不过,有几个快速警告供您参考。

          1. 这只会做表格。您需要扫描所有的存储过程和函数,以确保它们也更改为 NVARCHAR
          2. 如果您有一个VARCHAR > 4000,您需要将其修改为NVARCHAR(MAX)

          但是使用这个模板应该很容易做到。

          如果您希望它自动运行,您可以在WHILE 子句中设置它。

          【讨论】:

          • 请注意这一点,因为您将获得新列的所有默认值。例如,非空 varchar 将被创建为可为空的 nvarchar。
          【解决方案5】:

          以下查询应该可以满足您的需求:

          IF EXISTS 
            (SELECT *
             FROM sysobjects syo
             JOIN syscolumns syc ON
               syc.id = syo.id
             JOIN systypes syt ON
               syt.xtype = syc.xtype
             WHERE 
               syt.name = 'nvarchar' AND
               syo.name = 'MY TABLE NAME' AND
               syc.name = 'MY COLUMN NAME')
          BEGIN
             ALTER ...
          END
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-11
            • 1970-01-01
            • 2017-11-08
            • 1970-01-01
            • 2021-06-10
            • 2011-12-30
            相关资源
            最近更新 更多