我目前有一个列为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)
答案 0 :(得分:2)
行。我终于创建了一个有效的视图:
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]%')
感谢 AdaTheDev 和 CodeByMoonlight 。我用你的两个答案来解决这个问题。 (当然也要感谢其他回复者)
现在,当我与其他bigint cols连接或执行类似'SELECT * FROM MyView where mycol = 1'之类的操作时,它会返回正确的结果且没有错误。我的猜测是查询中的CAST本身会导致查询优化器不查看原始表格,正如Christian Hayter所说的可能会继续其他视图
答案 1 :(得分:1)
理想情况下,您希望尽量避免以这种形式存储数据 - 将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子句而不在where子句中所谓的bigint列上执行另一个CAST()的唯一方法是使用用户定义的函数:
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
我认为这不是一个明智的表现,但它是一个解决方案
答案 2 :(得分:1)
回答有关错误消息的问题:当您在另一个查询中引用视图名称时(假设它是传统视图而非物化视图),SQL Server有效地将视图定义宏替换为消费查询,然后执行。
这样做的好处是查询优化器可以在看到整个查询时做得更好,而不是将视图单独优化为“黑盒子”。
结果是,如果发生错误,错误描述可能看起来很混乱,因为执行引擎正在访问数据的基础表,而不是视图。
我不确定如何处理物化视图,但我认为它们被视为表,因为视图数据被缓存在数据库中。
话虽如此,我同意以前的答案 - 你应该重新考虑你的表格设计,并将文本和整数数据值分成不同的列。
答案 3 :(得分:1)
尝试将您的观点更改为:
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)
答案 4 :(得分:0)
您是否尝试将其他表格的bigint字段转换为varchar?至于我,执行更强大的转换是有意义的......如果varchar字段被索引,它不应该太大地影响你的性能。
答案 5 :(得分:0)
考虑创建一个冗余的bigint字段来保存af MyCol的整数值。
然后,您可以将新字段编入索引以加快连接速度。
答案 6 :(得分:0)
尝试分两个阶段进行选择。
首先创建一个视图,选择我的col为nummeric的所有列。
然后在该视图中执行选择以转换varchar字段。
您可以看到的另一件事是您的表格设计,以消除演员阵容的需要。
修改
答案 7 :(得分:0)
尝试使用:
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函数之前尝试强制转换(也许它与优化有关)。