将带有数字的列的类型从 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 中更改数据类型。

(您可能需要转到菜单 ToolsOptionsDesigners,并禁用阻止保存重新创建的更改的选项表。)

【讨论】:

那我不会失去所有的价值吗?? 没有。如果你愿意,可以在测试台上试试? 我刚刚完成了这项工作,效果很好。首先,我检查了所有现有值是否都是以字符串类型存储的数字,以及我是否可以成功地将所有 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 列的大小更改为较低的长度

数据类型从 varchar2 到日期、数字等的隐式转换

将现有 SQL Server 2005 数据库中的数据类型 varchar 更改为 nvarchar。有啥问题吗?

SQL Server 2008 - 从 Float 将列更改为 Varchar 产生科学记数法

SQL server 数据类型 - Date VS Varchar(n)