Fed*_*ust 1 stored-procedures sql-server-2008-r2 cursors alter-table
我正在尝试创建一个存储过程来将ntext
我的数据库中的所有列转换为nvarchar(max)
.
这是代码
ALTER PROCEDURE [dbo].[usp_SL_ConvertNtextToNvarchar]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @table_name nvarchar(128)
DECLARE @column_name nvarchar(128)
DECLARE @totalCount int
DECLARE @count int
SET @totalCount = 0;
SET @count = 0;
-- Eventlogic
DECLARE tables_cursor CURSOR FOR
SELECT so.name as table_name, sc.name as column_name
FROM sys.objects so
JOIN sys.columns sc ON so.object_id = sc.object_id
JOIN sys.types stp ON sc.user_type_id = stp.user_type_id
AND stp.name = 'ntext'
WHERE so.type = 'U' -- to show only user tables
OPEN tables_cursor
FETCH NEXT FROM tables_cursor INTO @table_name, @column_name
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC ('ALTER TABLE Eventlogic.dbo.' + @table_name + ' ALTER COLUMN ' + @column_name + ' nvarchar(max);')
EXEC ('UPDATE Eventlogic.dbo.' + @table_name + ' SET ' + @column_name + '=' + @column_name + ' ')
SET @count = @count + 1;
IF @count > 0
PRINT ('Eventlogic.dbo.' + @table_name + '.' + @column_name + ' ' + CAST(@count AS nvarchar(10)))
SET @totalCount = @totalCount + @count;
FETCH NEXT FROM tables_cursor INTO @table_name, @column_name
END
CLOSE tables_cursor
DEALLOCATE tables_cursor
PRINT ('Total columns updated: ' + CAST(@totalCount AS nvarchar(10)))
END;
Run Code Online (Sandbox Code Playgroud)
每当我尝试运行它时,都会收到此错误:
消息 16924,级别 16,状态 1,过程 usp_SL_ConvertNtextToNvarchar,第 37 行
Cursorfetch:INTO 列表中声明的变量数量必须与所选列的数量匹配。
我们在不同的表中有 338 列 ntext
由于遗留问题,。
我们升级到 SQL Server 2008 R2,因此我们想将这些列转换为 nvarchar(max)
.
我们希望遵循ntext vs nvarchar(max)中的建议,其中 Conwell 建议在更改后进行更新。
SQL Server 将文本从 LOB 结构移动到表中(如果小于 8,000 字节)。因此,当我们再次使用 IO STATISTICS 运行选择时,我们会得到 0 个 LOB 读取。
任何有关此错误的帮助都会很棒。
更新
更新了 Martin 提到的代码。在给出错误之前,它实际上只是改变了列表中的第一个。
第二次更新
在对代码进行更改以修复第二次提取后,我关闭了 SQL Management Studio。再次打开 SQL Management Studio 并运行它,它工作正常。所以再次感谢马丁。
提前致谢。
费德里科
如果您在阅读我的答案之前解决了这个问题,那么它不太可能对您的特定情况有用(除非您需要在多个数据库中执行此操作),但对于此类工作,我更喜欢字符串连接而不是游标。主要是因为您可以打印字符串而不是执行它,验证至少前 8K 值看起来正确无误。
DECLARE @sql NVARCHAR(MAX) = N'USE Eventlogic;';
SELECT @sql += N'
ALTER TABLE ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
+ ' ALTER COLUMN ' + QUOTENAME(c.name)
+ CASE WHEN c.system_type_id = 99 THEN ' N' ELSE ' ' END
+ 'VARCHAR(MAX)' + CASE WHEN c.is_nullable = 0 THEN ' NOT NULL' ELSE '' END
+ ';
UPDATE ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
+ ' SET ' + QUOTENAME(c.name) + ' = ' + QUOTENAME(c.name) + ';
PRINT ''' + QUOTENAME(s.name) + '.' + QUOTENAME(REPLACE(t.name,'''',''''''))
+ '.' + QUOTENAME(c.name) + ' ('
+ CONVERT(VARCHAR(12), COUNT(*) OVER(PARTITION BY c.[object_id]))
+ ' columns)'';'
FROM sys.columns AS c
INNER JOIN sys.tables AS t
ON c.[object_id] = t.[object_id]
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE c.system_type_id IN (35,99);
SET @sql += N'
PRINT ''Total columns updated: ' + CONVERT(VARCHAR(12), @@ROWCOUNT) + ''';';
PRINT @sql;
--EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)
当您对PRINT
输出感到满意时,取消注释EXEC
并再次运行它。
Jon Seigel 的脚本提供了额外的功能(处理参与 FULLTEXT 索引的列)。