【问题标题】:how to load varchar value into decimal datatype in sql server如何在sql server中将varchar值加载到十进制数据类型中
【发布时间】:2018-02-15 08:38:51
【问题描述】:

嗨,我对 sql server 有一个疑问。 当目标数据类型不同时,如何将数据从一个表加载到 sql server 中的另一个表。 我想将 emplatlng 值加载到 [destemplatlng] 表中。这里目标表 lat 和 lng 列的数据类型是十进制的,但是在 emplatlng 表具有 varchar 数据类型。

table : [emplatlng]
CREATE TABLE [dbo].[emplatlng](
    [pn_] [varchar](80) NULL,
    [lat] [varchar](50) NULL,
    [lng] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'1', N'47.6864739', N' -117.416422
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'2', N'47.6665465', N' -117.4166991
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'3', N'47.629512', N' -117.241304
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'5', N'47.6823378', N' -117.436788
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'7', N'47.644277', N' -117.348362
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'8', N'47.62510349999999', N' -117.5018943
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'10', N'47.6564638', N' -117.4110428
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'19', N'47.6693919', N' -117.4218557
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'56', N'48.4249897', N' -119.5020331
')
GO
INSERT [dbo].[emplatlng] ([pn_], [lat], [lng]) VALUES (N'32', N'48.4249778', N' -119.5020466
')
GO

destination table : 
CREATE TABLE [dbo].[destemplatlng](
    [pn_] [varchar](80) NULL,
    [lat] [decimal](9, 6) NULL,
    [lng] [decimal](9, 6) NULL
) 

我像下面这样颤抖:

insert into  destemplatlng
select pn_,convert( decimal(9,6),lat), convert( decimal(9,6),lng) from  emplatlng

它得到如下错误: 消息 8114,第 16 级,状态 5,第 1 行 将数据类型 varchar 转换为数值时出错。

请告诉我如何编写查询以在 sql server 中完成此任务

【问题讨论】:

  • -119.5020466 不能放入十进制 (9,6)
  • @sepupic,这将是一个艺术溢出错误,但也是个好地方。我想转换错误的原因是因为您的列[lng] 以空格开头,最后有一个回车/换行符。数字不包含其中任何一个,
  • 而 47.62510349999999 更糟。您应该提供正确的类型定义,并且只有您知道您的数字可以有多少位数字。如果您无法输入 38 位数字,请使用 float
  • 您可以转换您的 LAT,但您不能转换您的 LNG,因为它前面有空格并且它有 LineBreak。删除那些,你可以转换它。请注意,小数(9,6)会减少您的一些小数。 - 我刚刚通过删除您的空格和换行符对其进行了测试,并且效果很好。
  • @sepupic:我们在这里谈论纬度和经度; 8 位小数已经给出了精确到毫米的坐标,而 6 “仅仅”足以达到接近一米的精度。这里唯一的问题是常量中的换行符。

标签: sql-server sql-server-2008


【解决方案1】:

问题在于几件事。就像@sepupic 所说,您提供的数据的规模和准确性是错误的。 decimal(9,6) 最多只能存储 6 位小数,但是,您的某些数字的位数不止这些(例如 -117.5018943 有 7 个)。

此外,您的数字以空格开头,并以[lng] 列的换行符结束。数字没有这些字符。你需要把它们去掉。这似乎适用于我们拥有的示例数据(请注意,由于数据类型更改,我不得不重新创建目标表):

CREATE TABLE [dbo].[destemplatlng]([pn_] [varchar](80) NULL,
                                   [lat] decimal(15,12) NULL,
                                   [lng] decimal(15,12) NULL); 

GO
INSERT INTO destemplatlng
SELECT pn_,
       CONVERT(decimal(15,12),lat),
       CONVERT(decimal(15,12),REPLACE(REPLACE(REPLACE(lng,N' ',N''),NCHAR(10),N''), NCHAR(13),N''))
FROM  emplatlng;

从中学到的显而易见的事情是将数据存储在正确的数据类型中。不要将其他数据类型存储为 varchars;它最终只会导致更多它“解决”的问题。

【讨论】:

  • 你也可以只用 LTRIM 代替 '' 替换空格
  • @plaidDK 您可以,但是,考虑到 OP 在数字末尾也有换行符,我认为最好全面使用REPLACE(因为它们可能有带有空格的数据在其他“愚蠢”的地方,比如小数点旁边)。
猜你喜欢
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多