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