Sqlserver 修改字段类型
啪!贴代码:
-- ============================================= -- Author: 抹茶大虾球丶 -- Create date: 2021-04-27 -- Description: 修改字段类型,带有索引的字段会先删除索引,修改完字段类型后,重建索引 -- exec [grid].[FieldDataTypeModify] 'dbo.table1','Name','varchar(32)' -- ============================================= alter PROCEDURE [grid].[FieldDataTypeModify] @sTableName sysname, --表名带架构(eg. dbo.table1) @sColumnName sysname, --字段名 @sDataType sysname, --数据类型(eg. int、nvarchar(64)) @result sysname output, --执行结果,0:错误,1:正确 @errmsg sysname output --错误信息 AS BEGIN declare @sSql varchar(max), @sdType sysname, @sdLength int declare @tb_Indexes table(num int,index_name sysname, column_names sysname, column_order sysname, table_view sysname, index_type sysname, unique_type sysname, object_type sysname) declare @tb_Indexes_Bak table(num int,index_name sysname, column_names sysname,column_order sysname, table_view sysname, index_type sysname, unique_type sysname, object_type sysname) declare @nTbRowsCount int --@tb_Indexes数据行数 if not exists (select * from syscolumns a join systypes b on a.xtype=b.xtype where a.ID=object_id(@sTableName) and a.name=@sColumnName) begin set @result='0' set @errmsg='字段 '+@sColumnName+' 在表 '+@sTableName+' 中不存在!' return; end --获取索引信息 insert into @tb_Indexes select num = row_number() over(order by rg.name), rg.name as index_name, rg.column_names, left(rg.column_order,len(rg.column_order)-1) column_order, rg.table_view, case when rg.[type] = 1 then 'Clustered index' when rg.[type] = 2 then 'Nonclustered index' when rg.[type] = 3 then 'XML index' when rg.[type] = 4 then 'Spatial index' when rg.[type] = 5 then 'Clustered columnstore index' when rg.[type] = 6 then 'Nonclustered columnstore index' when rg.[type] = 7 then 'Nonclustered hash index' end as index_type, case when rg.is_unique = 1 then 'Unique' else '' --'Not Unique' end as unique_type, case when rg.obj_type = 'U' then 'Table' when rg.obj_type = 'V' then 'View' end as object_type from (select i.[name], substring(column_names, 1, len(column_names)-1) as column_names, column_order, i.[type], i.[is_unique], schema_name(t.schema_id) + '.' + t.[name] as table_view, t.[type] as obj_type from sys.objects t inner join sys.indexes i on t.object_id = i.object_id cross apply (select col.[name] + ',' from sys.index_columns ic inner join sys.columns col on ic.object_id = col.object_id and ic.column_id = col.column_id where ic.object_id = t.object_id and ic.index_id = i.index_id order by key_ordinal for xml path ('')) D (column_names) cross apply (select col.[name]+' '+ case ic.is_descending_key when 0 then 'ASC' else 'DESC' end + ',' from sys.index_columns ic inner join sys.columns col on ic.object_id = col.object_id and ic.column_id = col.column_id where ic.object_id = t.object_id and ic.index_id = i.index_id order by key_ordinal for xml path ('')) D1 (column_order) where t.is_ms_shipped <> 1 and index_id > 0 ) rg where ','+column_names+',' like '%,'+@sColumnName+',%' and rg.table_view=@sTableName --select * from @tb_Indexes --删除索引 declare @i int, @idxName sysname set @nTbRowsCount = (select count(*) from @tb_Indexes) if(@nTbRowsCount >0) begin insert into @tb_Indexes_Bak select * from @tb_Indexes while exists(select num from @tb_Indexes) begin set rowcount 1; select @i = num,@idxName=index_name from @tb_Indexes; set @sSql='drop index ['+ @idxName +'] on '+ @sTableName exec(@sSql) set rowcount 0; delete from @tb_Indexes where num=@i; end end --修改字段类型 set @sSql = 'alter table '+@sTableName+' alter column '+@sColumnName+' '+@sDataType+'' exec(@sSql) --重建索引 declare @idxFields sysname, @idxType sysname, @unique sysname set @i=0 set @idxName='' if(@nTbRowsCount >0) begin while exists(select num from @tb_Indexes_Bak) begin set rowcount 1; select @i = num, @idxFields=column_order, @idxName=index_name, @idxType=index_type, @unique=unique_type from @tb_Indexes_Bak; set @sSql='create '+ @unique +' '+ @idxType +' ['+ @idxName +'] on '+ @sTableName + '('+@idxFields+')' --print @sSql exec(@sSql) set rowcount 0; delete from @tb_Indexes_Bak where num=@i; end end delete @tb_Indexes delete @tb_Indexes_Bak set @result = '1' set @errmsg = '' END