转换数据类型时出错varchar

问题描述:

我目前有一个表,其列为varchar。此栏可以保存数字或文字。在某些查询我把它当作一个bigint转换数据类型时出错varchar

只要有唯一编号,在此领域没有任何麻烦,但一分钟甚至一列(它在别的表是bigint列之间我做一个连接)有这个字段中的文本和数字我得到了一个“错误转换数据类型varcharbigint”。错误,即使在WHERE部分我确保没有任何文本字段出现。

为了解决这个问题,我创建一个视图如下:

SELECT  TOP (100) PERCENT ID, CAST(MyCol AS bigint) AS MyCol 
FROM   MyTable 
WHERE  (isnumeric(MyCol) = 1) 

但即使视图只显示与数值的行蒙上Mycol为bigint我还得到一个错误转换数据类型为varchar为bigint运行下面的查询时:

SELECT * FROM MyView where mycol=1 

对视图做查询时它不应该知道是怎么回事就可以了后面!它应该只是看到两个bigint领域! (see attached image,即使mssql管理工作室显示视图字段为bigint)

+1

我个人认为你正在解决错误的问题。如果您为了两个不同的目的而使用一列,那么您的架构/数据库设计会出现问题。 – 2009-08-06 11:13:13

+1

是的,我知道,但整个系统现在已经太重要了 – adinas 2009-08-06 13:24:44

您是否尝试将其他表的bigint字段转换为varchar?对我来说,执行更强大的转换是有意义的...如果varchar字段被索引,它不应该太多地影响你的性能。

+0

这可能是一个解决方案,但真正让我感兴趣的是在视图上获取错误,即使它只有bigint字段 – adinas 2009-08-06 09:23:17

考虑创建一个多余的bigint字段来保存af MyCol的整数值。

然后,您可以对新字段编制索引以加快加入速度。

+0

这意味着更改我的项目的大部分,每次选择正确的领域... – adinas 2009-08-06 09:32:21

尝试在2个阶段做选择。

首先创建一个视图,用于选择列号为数字的所有列。

然后在该视图中进行select varchar字段的选择。

你可以看看的另一件事是你的表格设计,以消除对演员的需求。

编辑

  • 是一些数字比BIGINT大?
  • 有没有空格,领先,尾随或数字?
  • 是否有任何格式字符?小数点?
+0

试过。即使在查询第二个视图时,我仍然会得到相同的错误 – adinas 2009-08-06 09:31:08

理想情况下,您希望尽量避免以这种形式存储数据 - 将BIGINT数据分割为单独的列以提高性能和查询的便利性。

但是,您可以像本示例一样进行JOIN。请注意,我是未使用ISNUMERIC()来确定它是否是有效的BIGINT,因为它会验证会导致转换错误的错误值(例如十进制数)。

DECLARE @MyTable TABLE (MyCol VARCHAR(20)) 
DECLARE @OtherTable TABLE (Id BIGINT) 

INSERT @MyTable VALUES ('1') 
INSERT @MyTable VALUES ('Text') 
INSERT @MyTable VALUES ('1 and some text') 
INSERT @MyTable VALUES ('1.34') 
INSERT @MyTable VALUES ('2') 
INSERT @OtherTable VALUES (1) 
INSERT @OtherTable VALUES (2) 
INSERT @OtherTable VALUES (3) 

SELECT * 
FROM @MyTable m 
    JOIN @OtherTable o ON CAST(m.MyCol AS BIGINT) = o.Id 
WHERE m.MyCol NOT LIKE '%[^0-9]%' 

更新: 我可以找得到它,从而提供具有特定整数值的WHERE子句的工作没有做对所谓BIGINT列另一个CAST()在WHERE子句中过的唯一途径,是使用用户定义的函数:

CREATE FUNCTION [dbo].[fnBigIntRecordsOnly]() 
RETURNS @Results TABLE (BigIntCol BIGINT) 
AS 
BEGIN 
INSERT @Results 
SELECT CAST(MyCol AS BIGINT) 
FROM MyTable 
WHERE MyCol NOT LIKE '%[^0-9]%' 
RETURN 
END 

SELECT * FROM [dbo].[fnBigIntRecordsOnly]() WHERE BigIntCol = 1 

我真的不认为这是一个好主意性能明智的,但它是一个解决方案

尝试使用这样的:

SELECT 
    ID, 
    CAST(MyCol AS bigint) as MyCol 
FROM 
(
    SELECT TOP (100) PERCENT 
     ID, 
     MyCol 
    FROM 
     MyTable 
    WHERE 
     (isnumeric(MyCol) = 1) 
) as tmp 

这应该工作,因为内部只选择返回数值,外部选择因此可以将第一个选择的所有值转换为数字。看起来,在你自己的代码中,SQL试图在执行isnumeric函数之前进行强制转换(也许它与优化有关)。

+0

您的查询确实只返回包含数字的行。但是当它变成一个视图和查询视图我得到相同的'错误转换数据类型varchar到bigint'(只有当做“mycol = 1时我得到错误) – adinas 2009-08-06 09:55:50

要回答有关错误消息的问题:当您在另一个查询中引用视图名称时(假设它是传统视图而非实例化视图),SQL Server会有效地将视图定义的宏替换为消费查询,然后执行。

这样做的好处是,查询优化器如果能看到整个查询,可以做得更好,而不是单独将视图优化为“黑盒子”。

结果是,如果发生错误,错误描述可能会令人困惑,因为执行引擎正在访问数据的基础表,而不是视图。

我不知道物化视图是如何处理的,但我会想象它们被视为像表一样,因为视图数据被缓存在数据库中。

话虽如此,我同意以前的答案 - 您应该重新考虑您的表格设计,并将文本和整数数据值分隔为单独的列。

试着改变你的看法,以这样的:

SELECT TOP 100 PERCENT ID, 
Cast(Case When IsNumeric(MyCol) = 1 Then MyCol Else null End AS bigint) AS MyCol 
FROM MyTable 
WHERE (IsNumeric(MyCol) = 1) 
+0

对不起,这个查询返回相同的'错误转换数据类型varchar to bigint'err – adinas 2009-08-10 12:55:45

+0

您使用的是哪个版本的SQL Server?我已经在SQL2000中试过了,没有任何问题。 很高兴你找到了解决方案,无论如何:) – MartW 2009-08-10 15:57:41

确定。我终于创建了一个可行的观点:

SELECT TOP (100) PERCENT id, CAST(CASE WHEN IsNumeric(MyCol) = 1 THEN MyCol ELSE NULL END AS bigint) AS MyCol 
FROM   dbo.MyTable 
WHERE  (MyCol NOT LIKE '%[^0-9]%') 

由于AdaTheDevCodeByMoonlight。我用你的两个答案来解决这个问题。 (当然也要感谢其他的replier)

现在,当我与其他bigint cols连接或者执行像'SELECT * FROM MyView where mycol = 1'之类的操作时,它将返回正确的结果而不会出错。我的猜测是,在查询本身的CAST导致查询优化器不看原始表基督教海特说的可能发生的事情与其他视图

以下链接有这方面的一些细节: sql-server-peculiar-issue-error-converting-varchar-to-bigint

+0

这当然是一个翔实的文章。这种情况有所不同,但仍然很好知道。 – adinas 2012-01-03 12:31:44

+0

链接只有答案不欢迎堆栈溢出。 – hims056 2012-10-26 07:33:56