英文:
Microsoft SQL Server - How to convert all `ntext` columns to `nvarchar(max)` in tables and views?
问题
我需要在整个数据库中将所有 ntext
列替换为 nvarchar(max)
。在这种情况下,您需要对所有表和所有视图执行此操作。
我有以下代码,对于表格效果很好,但对于视图不起作用:
-- 创建一个临时表,其中将包含包含 ntext 类型字段的所有表
CREATE TABLE #TablesToModify
(
TableName NVARCHAR(255),
ColumnName NVARCHAR(255)
)
-- 用 ntext 类型的表和字段列表填充临时表
INSERT INTO #TablesToModify
SELECT c.TABLE_NAME, c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.DATA_TYPE = 'ntext'
-- 遍历每个表格并执行 ALTER TABLE 更改数据类型
DECLARE @TableName NVARCHAR(255)
DECLARE @ColumnName NVARCHAR(255)
DECLARE cur CURSOR FOR
SELECT TableName, ColumnName
FROM #TablesToModify
OPEN cur
FETCH NEXT FROM cur INTO @TableName, @ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
-- 执行 ALTER TABLE 更改数据类型
EXEC ('ALTER TABLE ' + @TableName + ' ALTER COLUMN ' + @ColumnName + ' NVARCHAR(MAX)')
FETCH NEXT FROM cur INTO @TableName, @ColumnName
END
CLOSE cur
DEALLOCATE cur
-- 删除临时表
DROP TABLE #TablesToModify
我应该添加什么来将 ntext
列类型更改为视图中的 nvarchar(max)
?
我在stackoverflow上找到了如何更改表中的所有列的解决方案,但没有找到如何在视图中更改它们的方法。
在互联网上,所有与此主题相关的信息都只涉及表格。
英文:
I need to replace all ntext
columns with nvarchar(max)
in the entire database. In this case, you need to do this for all tables and for all views.
I have the following code which works great for tables but doesn't work for views:
-- Create a temporary table that will contain all tables containing fields of type ntext
CREATE TABLE #TablesToModify
(
TableName NVARCHAR(255),
ColumnName NVARCHAR(255)
)
-- Fill the temporary table with a list of tables and fields of type ntext
INSERT INTO #TablesToModify
SELECT c.TABLE_NAME, c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.DATA_TYPE = 'ntext'
-- Go through each table and ALTER TABLE to change the data type
DECLARE @TableName NVARCHAR(255)
DECLARE @ColumnName NVARCHAR(255)
DECLARE cur CURSOR FOR
SELECT TableName, ColumnName
FROM #TablesToModify
OPEN cur
FETCH NEXT FROM cur INTO @TableName, @ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
-- Execute ALTER TABLE to change the data type
EXEC ('ALTER TABLE ' + @TableName + ' ALTER COLUMN ' + @ColumnName + ' NVARCHAR(MAX)')
FETCH NEXT FROM cur INTO @TableName, @ColumnName
END
CLOSE cur
DEALLOCATE cur
-- Delete temporary table
DROP TABLE #TablesToModify
What should I add to change the ntext
column type to nvarchar(max)
in views as well?
I found a solution on stackoverflow how to change all columns in tables but didn't find how to change them in views.
On the Internet, too, all information related to this topic refers only to tables.
答案1
得分: 3
你只需要在引用这些表的每个视图上调用 sp_refreshview
或 sp_refreshsqlmodule
。你可以从 sys.sql_expression_dependencies
中获取这些信息。
- 你需要添加模式名称。
- 对象名称应该是
sysname
。 - 不要使用
INFORMATION_SCHEMA
,它仅用于兼容性,并且可能不可靠。 - 你需要保持列的可空性。
- 对系统表上的游标可能不稳定。要么使用
STATIC
游标,要么更好地使用STRING_AGG
生成一个大的 SQL 脚本。
CREATE TABLE #TablesToModify
(
ObjectId bigint,
SchemaName sysname,
TableName sysname,
ColumnName sysname,
IsNullable bit
);
-- 使用 ntext 类型的表和字段列表填充临时表
INSERT INTO #TablesToModify (ObjectId, SchemaName, TableName, ColumnName, IsNullable)
SELECT
t.object_id, s.name, t.name, c.name, c.is_nullable
FROM sys.columns c
JOIN sys.types typ ON typ.user_type_id = c.user_type_id
JOIN sys.tables t ON t.object_id = c.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE typ.name = 'ntext';
DECLARE @sql nvarchar(max);
SELECT @sql = STRING_AGG(CAST(CONCAT(
'ALTER TABLE ',
QUOTENAME(SchemaName),
'.',
QUOTENAME(TableName),
' ALTER COLUMN ',
QUOTENAME(ColumnName),
' NVARCHAR(MAX)',
IIF(IsNullable = 1, N' NOT NULL;', N';')
) AS nvarchar(max)), ';
')
FROM #TablesToModify;
SELECT @sql += '
' + STRING_AGG(CAST(CONCAT(
'EXEC sp_refreshsqlmodule ''',
REPLACE(QUOTENAME(s.name) + '.' + QUOTENAME(o.name), '''', ''''''),
'''''
) AS nvarchar(max)), ';
')
FROM (
SELECT DISTINCT ObjectId
FROM #TablesToModify
) t
JOIN sys.sql_expression_dependencies d ON d.referenced_id = t.ObjectId
JOIN sys.objects o ON o.object_id = d.referencing_id
JOIN sys.schemas s ON s.schema_id = o.schema_id
GROUP BY
d.referencing_id;
PRINT @sql; -- your friend
EXEC sp_executesql @sql;
-- 删除临时表
DROP TABLE #TablesToModify
英文:
You just need to call sp_refreshview
or sp_refreshsqlmodule
on each view that references these tables. You can get this information out of sys.sql_expression_dependencies
- You need to add the schema name also.
- Object names should be
sysname
. - Don't use
INFORMATION_SCHEMA
it's for compatibility only and can be unreliable. - You need to maintain nullability of the column.
- Cursors on system tables can be iffy. Either use a
STATIC
cursor, or better just generate one big SQL script usingSTRING_AGG
.
CREATE TABLE #TablesToModify
(
ObjectId bigint,
SchemaName sysname,
TableName sysname,
ColumnName sysname,
IsNullable bit
);
-- Fill the temporary table with a list of tables and fields of type ntext
INSERT INTO #TablesToModify (ObjectId, SchemaName, TableName, ColumnName, IsNullable)
SELECT
t.object_id, s.name, t.name, c.name, c.is_nullable
FROM sys.columns c
JOIN sys.types typ ON typ.user_type_id = c.user_type_id
JOIN sys.tables t ON t.object_id = c.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE typ.name = 'ntext';
DECLARE @sql nvarchar(max);
SELECT @sql = STRING_AGG(CAST(CONCAT(
'ALTER TABLE ',
QUOTENAME(SchemaName),
'.',
QUOTENAME(TableName),
' ALTER COLUMN ',
QUOTENAME(ColumnName),
' NVARCHAR(MAX)',
IIF(IsNullable = 1, N' NOT NULL;', N';')
) AS nvarchar(max)), ';
' )
FROM #TablesToModify;
SELECT @sql += '
' + STRING_AGG(CAST(CONCAT(
'EXEC sp_refreshsqlmodule ''',
REPLACE(QUOTENAME(s.name) + '.' + QUOTENAME(o.name), '''', ''''''),
''''
) AS nvarchar(max)), '
' )
FROM (
SELECT DISTINCT ObjectId
FROM #TablesToModify
) t
JOIN sys.sql_expression_dependencies d ON d.referenced_id = t.ObjectId
JOIN sys.objects o ON o.object_id = d.referencing_id
JOIN sys.schemas s ON s.schema_id = o.schema_id
GROUP BY
d.referencing_id;
PRINT @sql; -- your friend
EXEC sp_executesql @sql;
-- Delete temporary table
DROP TABLE #TablesToModify
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论