将带有数字的列的类型从 varchar 更改为 int
Posted
技术标签:
【中文标题】将带有数字的列的类型从 varchar 更改为 int【英文标题】:Change type of a column with numbers from varchar to int 【发布时间】:2009-02-23 13:58:03 【问题描述】:我们在当前类型为 varchar(16) 的数据库中有两列。问题是,它包含数字并且总是包含数字。因此,我们希望将其类型更改为整数。但问题是它当然已经包含数据。
有什么方法可以将该列的类型从 varchar 更改为 int,而不会丢失所有已经存在的数字?希望我们可以运行某种 sql,而不必创建临时列并创建 C# 程序或其他东西来进行转换等等......我想如果 SQL Server 有一些函数可以将字符串转换为数字,但我在 SQL 上非常不稳定。几乎只能使用 C# 并通过 LINQ to SQL 访问数据库。
注意:是的,首先将列设为 varchar 并不是一个好主意,但不幸的是,他们就是这样做的。
【问题讨论】:
【参考方案1】:唯一可靠的方法是使用临时表,但不会使用太多 SQL:
select * into #tmp from bad_table
truncate table bad_table
alter bad_table alter column silly_column int
insert bad_table
select cast(silly_column as int), other_columns
from #tmp
drop table #tmp
【讨论】:
#tmp 是 tmp 表的随机名称? 好的答案 - 我会先运行这个 - 从 bad_table 中选择 cast(silly_column as int), other_columns 以确保您没有任何转换问题,它们实际上都是整数。 哈哈,不,不,我想知道 # 字符是否是使它成为临时表的原因。或者它只是任何不存在的名称,或者它是如何工作的...... 单个 # 表示特定于连接的临时表(仅在该连接中可用),而双哈希 ## 表示全局临时表(所有连接均可访问) sigh 由于外键约束,截断不起作用。我可以在弄乱它时以某种方式禁用它,然后再将其重新打开吗?【参考方案2】:最简单的方法是:
alter table myTable alter column vColumn int;
只要
-
所有数据都适合 int 格式
所有数据都可以转换为 int(即“car”的值将失败)
没有包含 vColumn 的索引。如果有索引,您将需要添加一个 drop 并创建它们以使它们回到原来的位置。
【讨论】:
@svish:我真的希望它是“汽车”而不是“字符”。 哦!对不起。现在明白你的意思了,嘿嘿:) 这很奏效。尝试通过管理工作室时失败 @jmoreno 有什么办法可以用order by LENGTH(col)
更改或更新表???
@AshishKamble:这必须是一个单独的问题,更多的细节解释你想要什么。【参考方案3】:
只需在 SQL Server Management Studio 中更改数据类型。
(您可能需要转到菜单 Tools → Options → Designers,并禁用阻止保存重新创建的更改的选项表。)
【讨论】:
那我不会失去所有的价值吗?? 没有。如果你愿意,可以在测试台上试试? 我刚刚完成了这项工作,效果很好。首先,我检查了所有现有值是否都是以字符串类型存储的数字,以及我是否可以成功地将所有 varchars 转换为数字类型。在我禁用对列(索引、键、触发器等)的所有引用并继续应用 MSSMS 中的更改之后。太好了! 这对我来说失败了,但上面的 alter table 语句有效 在设计菜单中的 SSMS 中执行 对于大表 可能会预先警告您:Saving Definition Changes to tables with large amounts of data could take a considerable amount of time. While changes are being saved, table data will not be accessible.
,或者可能会失败:- Unable to modify table. Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
,除非您更改 Tools → Options → Designers
选项“覆盖表设计器更新的连接字符串超时”。我也认为ALTER TABLE
声明对我来说可能更好。【参考方案4】:
我非常感谢以前的答案,但也认为更完整的答案会对其他搜索者有所帮助...
如果您在生产类型表上进行更改,有几个注意事项会有所帮助。
-
如果您在表上定义了 identity 列,则必须在重新插入数据时将
IDENTITY_INSERT
设置为打开和关闭。您还必须使用明确的列列表。
如果您想确保不会杀死数据库中的数据,请在 truncate/alter/reinsert 过程周围使用TRANSACTIONS
如果您有大量数据,则尝试仅在 SQ Server Management Studio 中进行更改可能会因超时而失败,并且您可能会丢失数据。
要扩展@cjk 给出的答案,请查看以下内容:
注意:'tuc' 只是此脚本中真实表名的占位符
begin try
begin transaction
print 'Selecting Data...'
select * into #tmp_tuc from tuc
print 'Truncating Table...'
truncate table tuc
alter table tuc alter column someColumnName someDataType [not null]
... Repeat above until done
print 'Reinserting data...'
set identity_insert tuc on
insert tuc (
<Explicit column list (all columns in table)>
)
select
<Explicit column list (all columns in table - same order as above)>
from #tmp_tuc
set identity_insert tuc off
drop table #tmp_tuc
commit
print 'Successful!'
end try
begin catch
print 'Error - Rollback'
if @@trancount > 0
rollback
declare @ErrMsg nvarchar(4000), @ErrSeverity int
select @ErrMsg = ERROR_MESSAGE(), @ErrSeverity = ERROR_SEVERITY()
set identity_insert tuc off
RAISERROR(@ErrMsg, @ErrSeverity, 1)
end catch
【讨论】:
以上是关于将带有数字的列的类型从 varchar 更改为 int的主要内容,如果未能解决你的问题,请参考以下文章
Oracle SQL 在包含数据时将列类型从数字更改为 varchar2
Postgresql - 将 varchar 列的大小更改为较低的长度
将现有 SQL Server 2005 数据库中的数据类型 varchar 更改为 nvarchar。有啥问题吗?