如何用SQL语句写修改数据库字段数据类型?

时间:2021-01-23 07:23:14
有一数据库的一个字段为Int型,现想将它改为有标识(自动增加)的Int,SQL语句该怎么写?

4 个解决方案

#1


没有直接修改的语句.

#2


--参考这个.

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_ToIDENTITY]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_ToIDENTITY]
GO

/*--普通列转换为标识列

采用修改表名,然后按新规则建表的方法处理
只适用于没有与其他对象有关联的表
转换后,列的相关对象也不会恢复
因此这种处理有很大局限性,仅供参考

--邹建 2005.05(引用请保留此信息)--*/

/*--调用示例

EXEC p_ToIDENTITY 'tb','id'

--使用测试

--创建测试的表
create table tb(编号 bigint,姓名 varchar(10))
insert tb select 1,'张三'
union all select 2,'李四'
union all select 4,'王五'
go

--调用存储过程,将编号字段改为标识字段
exec p_ToIDENTITY 'tb','编号'
go

--显示处理结果
select * from tb

--显示是否修改成功
select name from syscolumns 
where object_id('tb')=id and status=0x80
go

--删除测试
drop table tb
--*/
CREATE PROC p_ToIDENTITY
@TableName sysname, --要处理的表名
@FieldName sysname, --要转换的列名,必须是整型数据字段
@increment int=1    --标识值的增量
AS
IF ISNULL(OBJECTPROPERTY(OBJECT_ID(@TableName),N'IsUserTable'),0)=0
BEGIN
RAISERROR('"%s" 必须是当前数据库中已经存在的用户表',12,16,@TableName)
RETURN
END

--标识列转换处理检查
DECLARE @s1 nvarchar(1000),@s2 nvarchar(4000),@bkTableName sysname
SELECT @s2='',@bkTableName=CAST(NEWID() as char(36)),
@s1=CASE
WHEN c.status=0x80 
THEN N'表"%s"中已经有标识列'+QUOTENAME(c.name,N'"')
+N',列"%s"不能再被转换成标识列'
WHEN t.name LIKE '%int' 
THEN N','+QUOTENAME(c.name)
+N'=IDENTITY('+QUOTENAME(t.name)
+N',1,'+CAST(@increment as varchar)+N')'
WHEN c.scale=0 AND t.name IN(N'decimal',N'numeric') 
THEN N','+QUOTENAME(c.name)
+N'=IDENTITY('+QUOTENAME(t.name)
+N'('+CAST(c.prec as varchar)+N')'
+N',1,'+CAST(@increment as varchar)+N')'
ELSE N'表"%s"中的列"%s"定义"'+QUOTENAME(t.name)
+CASE WHEN c.scale>0 
THEN N'('+CAST(c.prec as varchar)
+N','+CAST(c.scale as varchar)+N')'
ELSE N'' END
+N'无效,不能转换为标识列'
END
FROM sysobjects o,syscolumns c,systypes t
WHERE o.name=@TableName
AND o.id=c.id
AND c.xusertype=t.xusertype
AND(c.name=@FieldName OR c.status=0x80)
IF @@ROWCOUNT=0
BEGIN
RAISERROR(N'表 "%s" 中无列 "%s"',12,16,@TableName,@FieldName)
RETURN
END
IF LEFT(@s1,1)<>','
BEGIN
RAISERROR(@s1,12,16,@TableName,@FieldName)
RETURN
END

--生成要处理的列
SELECT @s2=@s2+N','+QUOTENAME(c.name)
FROM sysobjects o,syscolumns c
WHERE o.name=@TableName
AND o.id=c.id
ORDER BY c.colid
SELECT @s1=REPLACE(@s2+N',',N','+QUOTENAME(@FieldName)+N',',@s1+N','),
@s1=SUBSTRING(@s1,2,LEN(@s1)-2),
@s2=STUFF(@s2,1,1,N'')

--修改原表名
EXEC sp_rename @TableName,@bkTableName

--转换为标识列处理
SELECT @TableName=QUOTENAME(@TableName),
@bkTableName=QUOTENAME(@bkTableName)
EXEC('
SELECT '+@s1+' INTO '+@TableName+N' 
FROM '+@bkTableName+' WHERE 1=0
SET IDENTITY_INSERT '+@TableName+N' ON
INSERT '+@TableName+N'('+@s2+N')
SELECT '+@s2+N' FROM '+@bkTableName+N'
SET IDENTITY_INSERT '+@TableName+N' OFF
DROP TABLE '+@bkTableName)
GO

#3


alter table tt drop column a --a 为原来的int 
alter table tt add a int identity(1,1)

#4


不能将原来的字段删除,实在不行只能在企业管理器里改啦,谢谢!

#1


没有直接修改的语句.

#2


--参考这个.

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_ToIDENTITY]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_ToIDENTITY]
GO

/*--普通列转换为标识列

采用修改表名,然后按新规则建表的方法处理
只适用于没有与其他对象有关联的表
转换后,列的相关对象也不会恢复
因此这种处理有很大局限性,仅供参考

--邹建 2005.05(引用请保留此信息)--*/

/*--调用示例

EXEC p_ToIDENTITY 'tb','id'

--使用测试

--创建测试的表
create table tb(编号 bigint,姓名 varchar(10))
insert tb select 1,'张三'
union all select 2,'李四'
union all select 4,'王五'
go

--调用存储过程,将编号字段改为标识字段
exec p_ToIDENTITY 'tb','编号'
go

--显示处理结果
select * from tb

--显示是否修改成功
select name from syscolumns 
where object_id('tb')=id and status=0x80
go

--删除测试
drop table tb
--*/
CREATE PROC p_ToIDENTITY
@TableName sysname, --要处理的表名
@FieldName sysname, --要转换的列名,必须是整型数据字段
@increment int=1    --标识值的增量
AS
IF ISNULL(OBJECTPROPERTY(OBJECT_ID(@TableName),N'IsUserTable'),0)=0
BEGIN
RAISERROR('"%s" 必须是当前数据库中已经存在的用户表',12,16,@TableName)
RETURN
END

--标识列转换处理检查
DECLARE @s1 nvarchar(1000),@s2 nvarchar(4000),@bkTableName sysname
SELECT @s2='',@bkTableName=CAST(NEWID() as char(36)),
@s1=CASE
WHEN c.status=0x80 
THEN N'表"%s"中已经有标识列'+QUOTENAME(c.name,N'"')
+N',列"%s"不能再被转换成标识列'
WHEN t.name LIKE '%int' 
THEN N','+QUOTENAME(c.name)
+N'=IDENTITY('+QUOTENAME(t.name)
+N',1,'+CAST(@increment as varchar)+N')'
WHEN c.scale=0 AND t.name IN(N'decimal',N'numeric') 
THEN N','+QUOTENAME(c.name)
+N'=IDENTITY('+QUOTENAME(t.name)
+N'('+CAST(c.prec as varchar)+N')'
+N',1,'+CAST(@increment as varchar)+N')'
ELSE N'表"%s"中的列"%s"定义"'+QUOTENAME(t.name)
+CASE WHEN c.scale>0 
THEN N'('+CAST(c.prec as varchar)
+N','+CAST(c.scale as varchar)+N')'
ELSE N'' END
+N'无效,不能转换为标识列'
END
FROM sysobjects o,syscolumns c,systypes t
WHERE o.name=@TableName
AND o.id=c.id
AND c.xusertype=t.xusertype
AND(c.name=@FieldName OR c.status=0x80)
IF @@ROWCOUNT=0
BEGIN
RAISERROR(N'表 "%s" 中无列 "%s"',12,16,@TableName,@FieldName)
RETURN
END
IF LEFT(@s1,1)<>','
BEGIN
RAISERROR(@s1,12,16,@TableName,@FieldName)
RETURN
END

--生成要处理的列
SELECT @s2=@s2+N','+QUOTENAME(c.name)
FROM sysobjects o,syscolumns c
WHERE o.name=@TableName
AND o.id=c.id
ORDER BY c.colid
SELECT @s1=REPLACE(@s2+N',',N','+QUOTENAME(@FieldName)+N',',@s1+N','),
@s1=SUBSTRING(@s1,2,LEN(@s1)-2),
@s2=STUFF(@s2,1,1,N'')

--修改原表名
EXEC sp_rename @TableName,@bkTableName

--转换为标识列处理
SELECT @TableName=QUOTENAME(@TableName),
@bkTableName=QUOTENAME(@bkTableName)
EXEC('
SELECT '+@s1+' INTO '+@TableName+N' 
FROM '+@bkTableName+' WHERE 1=0
SET IDENTITY_INSERT '+@TableName+N' ON
INSERT '+@TableName+N'('+@s2+N')
SELECT '+@s2+N' FROM '+@bkTableName+N'
SET IDENTITY_INSERT '+@TableName+N' OFF
DROP TABLE '+@bkTableName)
GO

#3


alter table tt drop column a --a 为原来的int 
alter table tt add a int identity(1,1)

#4


不能将原来的字段删除,实在不行只能在企业管理器里改啦,谢谢!