one*_*com 3 sql-server alter-table sql-server-2012
我在 mssql 2012 中拥有包含 170 多个表的数据库。其中一些包含字段“UserID”、varchar(9) 而另一些则不包含。由于应用程序重新设计,我需要更改数据库中的所有表以检查该字段是否存在,如果存在,我需要将其更改为 varchar(50)。如果没有,那么我需要添加它。
有人可以指出我如何使用某种批处理程序来做到这一点吗?我对 mssql 数据库没有太多经验,因此将不胜感激。
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += [sql] FROM
(
SELECT [sql] = N'
ALTER TABLE '
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
+ ' ALTER COLUMN ' + c.name + ' VARCHAR(50);'
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 LOWER(c.name) = N'userid'
AND c.max_length < 50
UNION ALL
SELECT N'
ALTER TABLE '
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
+ ' ADD UserID VARCHAR(50);'
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE NOT EXISTS
(
SELECT 1 FROM sys.columns
WHERE LOWER(name) = N'userid'
AND [object_id] = t.[object_id]
)
) AS x;
PRINT @sql;
--EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)
如果字符串太长而无法通过 PRINT 正确验证,请参阅此提示以了解其他想法。
您还需要确保更新任何将其作为varchar(9)
参数的存储过程,因为这些过程会以静默方式截断,以及您在即席 SQL、视图和其他模块等中执行的任何显式转换或变量声明。例如,如果您有两个用户,一个 ID = frankenstein
,另一个只是frankenst
:
DECLARE @UserID VARCHAR(9) = 'frankenstein';
SELECT @UserID;
Run Code Online (Sandbox Code Playgroud)
结果:
frankenst -- this will match the wrong user!
Run Code Online (Sandbox Code Playgroud)
这是一个执行以下操作的查询:
use YourDatabase;
go
select
object_name =
object_name(c.object_id),
column_name = c.name,
type_name = t.name,
c.max_length,
alter_table_ddl =
'alter table ' +
quotename(object_schema_name(c.object_id)) + '.' +
quotename(object_name(c.object_id)) +
' alter column ' + quotename(c.name) +
' varchar(50);'
from sys.columns c
inner join sys.types t
on c.system_type_id = t.system_type_id
where c.name = 'UserID'
--and c.max_length = 9;
Run Code Online (Sandbox Code Playgroud)
您可以取消注释最后一行(用于过滤的 AND 子句)以仅提取数据库中 varchar(9) 的列。
因此,此查询将标识您关注的列,并且查询结果集的最后一列将是ALTER TABLE ... ALTER COLUMN
DDL,它应该是进行列更改的 T-SQL 文本。
听起来这可能是一个非生产环境/数据库,但值得一提的是,要实际进行所有这些更改,此操作可能具有极大的侵入性。无论哪种方式,请确保最终用户的影响最小,并确保您在执行此操作之前拥有此数据库的有效备份。同样,查看查询的输出。永远不要只获取输出,尤其是生成 DDL 的输出,然后盲目地执行它。
编辑:我完全错过了您的问题的一部分,如果该列不存在,您的要求也是添加该列。抱歉,我不会重做 Aaron 的工作,因为他似乎已经满足了该要求。