如何在SQL查询中轻松地将所有ntext字段转换为nvarchar(max)?

如何在SQL查询中轻松地将所有ntext字段转换为nvarchar(max)?,sql,sql-server,Sql,Sql Server,我希望能够在不枚举列的情况下编写SQL查询,这将返回所有列,以及任何转换为varchar(max)的ntext列。我想知道是否有一个聪明的方法来做到这一点 这将非常好,因为这样我就可以对这样的查询执行基于比较的操作符,比如UNION,EXCEPT等等。netxt列是不可比较的,因此在使用这些运算符时失败 我当前的想法: 创建一个函数以将查询构建为动态sql。类似于此: 有更好的办法吗 谢谢你的意见 NTEXT无论如何都将从SQl Server的未来版本中删除(),所以为什么不咬紧牙关,将列更改为

我希望能够在不枚举列的情况下编写SQL查询,这将返回所有列,以及任何转换为varchar(max)的ntext列。我想知道是否有一个聪明的方法来做到这一点

这将非常好,因为这样我就可以对这样的查询执行基于比较的操作符,比如UNION,EXCEPT等等。netxt列是不可比较的,因此在使用这些运算符时失败

我当前的想法:

创建一个函数以将查询构建为动态sql。类似于此:

有更好的办法吗


谢谢你的意见

NTEXT
无论如何都将从SQl Server的未来版本中删除(),所以为什么不咬紧牙关,将列更改为
NVARCHAR(MAX)
?一次可能很昂贵,但可能值得:

ALTER TABLE dbo.T ALTER COLUMN NTextColumn NVARCHAR(MAX) NULL; -- OR NOT NULL
您可以使用以下方法为整个数据库生成和执行脚本:

DECLARE @SQL NVARCHAR(MAX) = 
    (   SELECT  'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + 
                                QUOTENAME(OBJECT_NAME(object_id)) + 
                                ' ALTER COLUMN ' + QUOTENAME(Name) + 
                                ' NVARCHAR(MAX) ' + 
                                CASE WHEN is_nullable = 0 THEN 'NOT' ELSE '' END + 
                                ' NULL;' + CHAR(13) + 'GO' + CHAR(13)
        FROM    sys.columns
        WHERE   system_type_id = 99 --NTEXT
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)');

EXECUTE sp_executesql @SQL;
我使用这个光标(这里恐怕没有基于集合的替代方案)来实现:

DECLARE TableCursor CURSOR FAST_FORWARD 
FOR
    SELECT 
        t.Name,
        c.name,
        c.is_nullable, 
        typ.user_type_id
    FROM 
        sys.columns c 
    INNER JOIN 
        sys.tables t ON c.object_id = t.object_id
    INNER JOIN 
        sys.types typ ON c.system_type_id = typ.system_type_id
    WHERE   
        typ.name IN ('text', 'ntext')    -- user_type_id: text = 35, ntext = 99 

DECLARE @TableName sysname, @ColumnName sysname, @IsNullable BIT, @TypeID INT

OPEN TableCursor

FETCH NEXT FROM TableCursor INTO @TableName, @ColumnName, @IsNullable, @TypeID

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @Stmt NVARCHAR(999)

    SET @Stmt = 'ALTER TABLE dbo.[' + @TableName + '] ALTER COLUMN [' + @ColumnName + '] ' + 
              CASE @TypeID 
                WHEN 35 THEN ' VARCHAR(MAX) '
                WHEN 99 THEN ' NVARCHAR(MAX) '
              END  + 
                CASE WHEN @IsNullable = 1 THEN 'NULL' ELSE 'NOT NULL' END

    PRINT @Stmt
    EXEC (@Stmt)

    FETCH NEXT FROM TableCursor INTO @TableName, @ColumnName, @IsNullable, @TypeID
END

CLOSE TableCursor
DEALLOCATE TableCursor
我简化了我的代码,假设我的所有表都在
dbo
模式中-如果您不是这样,那么您也必须包括
sys.schema
目录视图中的模式


运行此代码将一次性地将所有
text
转换为
varchar(max)
,将所有
ntext
转换为
nvarchar(max)
,您与
text/ntext
的所有问题将永远消失!:-)

这是我对上面GarethD答案的修改版本。SQL找不到某些表时出现问题,因此我使用sys.tables与sys.columns连接。此外,is_nullable行不正确(如果字段不可为NULL,则将其设置为not NULL)


说得好。不幸的是,我在图腾柱上的高度不够高,无法做出这一举动:)然后告诉那些在图腾柱上足够高的人做出改变,如果他们达到如此高的高度,他们可能会意识到你的建议是好的?任何其他解决方案都只是将问题掩盖起来。只是“做出改变”的精彩脚本,+1它应该是is_nullable=0,然后是'NOT',别忘了更新文本字段以避免巨大的性能损失。在表被修改后,我刚刚插入了这些行:
SET@Stmt='updatedbo.['+@TableName+']SET['+@ColumnName+']=['+@ColumnName+']'PRINT@Stmt EXEC(@Stmt)
@cjbarth:啊,你链接到的帖子很有趣-谢谢你的提醒!这对我有用:。。我将脚本的
INSERT
部分修改为
,其中o.type='U'和c.system_type_id在(99,35)中
DECLARE @SQL NVARCHAR(MAX) = ' ';

SELECT  @SQL = @SQL + ' ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(sys.columns.object_id)) + '.' + 
                        QUOTENAME(OBJECT_NAME(sys.columns.object_id)) + 
                        ' ALTER COLUMN ' + QUOTENAME(sys.columns.Name) + 
                        ' NVARCHAR(MAX) ' + 
                        CASE WHEN is_nullable = 0 THEN 'NOT NULL' ELSE '' END 

FROM    sys.Tables
inner join sys.columns on sys.tables.object_id = sys.columns.object_id
WHERE   sys.columns.system_type_id = 99 ; --NTEXT 

EXECUTE sp_executesql @SQL;
GO