【问题标题】:Error converting data type varchar转换数据类型 varchar 时出错
【发布时间】:2010-11-17 06:58:26
【问题描述】:

我目前有一个表,其列为varchar。此列可以包含数字或文本。在某些查询中,我将其视为bigint 列(我在它与另一个表中的列bigint 之间进行连接)

只要此字段中只有数字就没有问题,但即使一行有文本而不是此字段中的数字,我也会收到“将数据类型 varchar 转换为 bigint 时出错。”即使在 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)

【问题讨论】:

  • 我个人认为你正在解决错误的问题。如果您将一列用于两种不同的目的,那么您的架构/数据库设计就会出现问题。
  • 是的,我知道,但整个系统现在还太远,无法进行重大更改
  • 以下链接对此有一些详细信息:sql-server-peculiar-issue-error-converting-varchar-to-bigint

标签: sql sql-server tsql


【解决方案1】:

好的。我终于创建了一个有效的视图:

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。我用你的两个答案来解决这个问题。 (当然也感谢其他回复者)

现在,当我加入其他 bigint cols 或执行类似 'SELECT * FROM MyView where mycol=1' 之类的操作时,它会返回正确的结果且没有错误。我的猜测是查询本身中的 CAST 会导致查询优化器不查看原始表,正如 Christian Hayter 所说的那样,其他视图可能会继续

【讨论】:

  • 如果你仍然认为这个答案是最正确的,那么你应该接受它作为答案。这会将您的问题从仍未解决的问题列表中删除。
【解决方案2】:

理想情况下,您希望避免以这种形式存储数据 - 值得将 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]%'

更新: 我能找到的唯一方法是使用用户定义的函数:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    我不确定具体化视图是如何处理的,但我可以想象它们被视为表,因为视图数据缓存在数据库中。

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

    【讨论】:

      【解决方案4】:

      尝试将您的视图更改为:

      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)
      

      【讨论】:

      • 对不起,这个查询返回了同样的“将数据类型 varchar 转换为 bigint 时出错”错误
      • 您使用的是什么版本的 SQL Server?我已经在 SQL2000 及更高版本中尝试过,没有任何问题。很高兴你找到了解决方案,无论如何:)
      【解决方案5】:

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

      【讨论】:

      • 这可能是一个解决方案,但真正让我感兴趣的是,即使它只有 bigint 字段,也会在视图上显示错误
      【解决方案6】:

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

      然后您可以索引新字段以加快连接速度。

      【讨论】:

      • 这意味着每次都要更改我项目的大部分以选择正确的字段...
      【解决方案7】:

      试试这个:

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

      这应该可以工作,因为内部选择只返回数字值,因此外部选择可以将第一个选择的所有值转换为数字。似乎在您自己的代码中,SQL 会在执行 isumeric 函数之前尝试强制转换(可能与优化有关)。

      【讨论】:

      • 您的查询确实只返回带数字的行。但是当将其转换为视图并查询视图时,我得到相同的“将数据类型 varchar 转换为 bigint 时出错”(仅在执行“where mycol=1”时出现错误)
      【解决方案8】:

      尝试分两个阶段进行选择。

      首先创建一个视图,选择我的 col 为数字的所有列。

      然后在您投射 varchar 字段的那个视图中进行选择。

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

      编辑

      • 某些数字是否大于 bigint?
      • 是否有空格、前导、尾随或数字?
      • 是否有任何格式字符?小数点?

      【讨论】:

      • 试过了。即使在查询第二个视图时,我仍然会遇到同样的错误
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多