C# SQL执行错误。将数据类型nvarchar转换为实数时出错
目前,我正在对一个开始失败的SQL Server 2008查询进行故障排除。以下是查询:C# SQL执行错误。将数据类型nvarchar转换为实数时出错,c#,sql,C#,Sql,目前,我正在对一个开始失败的SQL Server 2008查询进行故障排除。以下是查询: SELECT TOP (100) PERCENT dbo.tblBenchmarkData.FieldDataSetID, dbo.tblBC.BCID, CAST(dbo.tblBenchmarkData.DataValue AS float(8)) AS DataValue, dbo.tblBC.BCMnemonic, dbo.tblDataType.Dat
SELECT TOP (100) PERCENT dbo.tblBenchmarkData.FieldDataSetID, dbo.tblBC.BCID, CAST(dbo.tblBenchmarkData.DataValue AS float(8)) AS DataValue,
dbo.tblBC.BCMnemonic, dbo.tblDataType.DataTypeMnemonic
FROM dbo.tblFieldDataSet RIGHT OUTER JOIN
dbo.tblBenchmarkData ON dbo.tblFieldDataSet.FieldDataSetID = dbo.tblBenchmarkData.FieldDataSetID LEFT OUTER JOIN
dbo.tblBC LEFT OUTER JOIN
dbo.tblDataType ON dbo.tblBC.DataTypeID = dbo.tblDataType.DataTypeID RIGHT OUTER JOIN
dbo.tblZEGCode ON dbo.tblBC.BCID = dbo.tblZEGCode.BCID ON dbo.tblBenchmarkData.ZEGCodeID = dbo.tblZEGCode.ZEGCodeID
WHERE (dbo.tblDataType.DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}') AND (dbo.tblFieldDataSet.OriginalFieldDataSetID IS NULL) AND
(dbo.tblFieldDataSet.Duplicate = 0)
ORDER BY dbo.tblBC.BCMnemonic, DataValue
当我删除强制转换并执行查询时,它返回大约1400000行,因此我获取DataValue结果并对该输出运行一个小型C#程序,以验证所有数据实际上都是数字:
List<String> lstLinesOfFile = new List<string>();
Int64 intLineCounter = 0;
ReadFile("data.txt");
double dblNum;
foreach (string strValue in lstLinesOfFile)
{
bool isNum = double.TryParse(strValue, out dblNum);
if (!isNum)
{
Debug.WriteLine("Line: " + Convert.ToString(intLineCounter) + ", Value = " + strValue);
}
intLineCounter++;
}
更新2:
从完整的原始视图粘贴上面的代码。乍一看,您似乎没有将c代码连接到sql查询 下面的行将1stLinesOffline设置为字符串的空列表,但您从未将其设置为任何其他值,因此for循环将永远不会运行 List lstLinesOfFile=新列表() 我希望看到 列表1stLinesOfFile=mySqlResults
其中mySqlResults是SQL的结果数据集。乍一看,您似乎没有将c代码连接到SQL查询 下面的行将1stLinesOffline设置为字符串的空列表,但您从未将其设置为任何其他值,因此for循环将永远不会运行 List lstLinesOfFile=新列表() 我希望看到 列表1stLinesOfFile=mySqlResults
其中,mySqlResults是SQL的结果数据集。使用它可以确定哪些值不能被SQL解析
select * from tblBenchData where ISNUMERIC(DataValue) = 0
还是这个
select * from tblBenchData where DataValue like '%[a-Z]%'
我猜这可能是一个区域性问题(例如“,”vs“)使用它来找出哪些值不能被SQL解析
select * from tblBenchData where ISNUMERIC(DataValue) = 0
还是这个
select * from tblBenchData where DataValue like '%[a-Z]%'
我猜可能是一个文化问题(例如“,”vs“)您在该查询中使用了右外连接和左外连接语法;但您在右/左联接表上使用where子句。这有点恶心,可能没有达到你的预期 我首先在
tblBenchData
表中查看哪些DataSetID返回为null
比如:
SELECT *
FROM tblDataSet
WHERE DataSetID NOT EXISTS IN (SELECT DataSetID FROM tblBenchData)
接下来,我猜您在复制/粘贴时遗漏了一些内容,因为tblBenchCode
上的左外部联接没有on
条件。您能提供实际使用的查询吗
旁注:我不完全确定您为什么拥有顶部(100%)部分。我知道在视图中允许order by定义是一个不可靠的把戏,但它在今天毫无意义,在您提供的查询中也毫无意义。。。除非这是一个古老的SQL server
另一种可能性是,正如Loud所指出的,一年前的问题表明您的值位于…您在该查询中使用了右外和左外连接语法;但您在右/左联接表上使用where子句。这有点恶心,可能没有达到你的预期
我首先在tblBenchData
表中查看哪些DataSetID返回为null
比如:
SELECT *
FROM tblDataSet
WHERE DataSetID NOT EXISTS IN (SELECT DataSetID FROM tblBenchData)
接下来,我猜您在复制/粘贴时遗漏了一些内容,因为tblBenchCode
上的左外部联接没有on
条件。您能提供实际使用的查询吗
旁注:我不完全确定您为什么拥有顶部(100%)部分。我知道在视图中允许order by定义是一个不可靠的把戏,但它在今天毫无意义,在您提供的查询中也毫无意义。。。除非这是一个古老的SQL server
另一种可能性是,正如Loud指出的,您一年前的问题表明您的值在…中。出现此问题的原因是有大量奇数字符串将通过ISNUMERIC()
测试,但无法CAST()
浮动(并且仍然可以通过double.TryParse
进行兑换)。据我所知,有三种:
- “+”
- “.”
- “——”
这里有一种方法可以捕捉其中一些:
SELECT DataValue
FROM dbo.tblBenchData
WHERE ISNUMERIC('0'+DataValue) = 0
奇怪的是,这将正确地转换或无误地拒绝其中大多数:
SELECT CAST('0'+DataValue As float(8)) As DataValue
FROM dbo.tblBenchData
WHERE ISNUMERIC('0'+DataValue) = 0
不过仍然有一些奇怪的案例可以通过
好的,我忘记了这个技巧不喜欢有效的负值
至于“其他”奇怪的情况,我真的记不清它们的全部,也从来没有在任何地方见过它们(我知道,这真的很烦人)。然而,大多数问题字符串都来自不同的数字解析器如何看待所谓的“退化情况”,即单字符字符串
因此,解决这两个问题的一种方法是预先检查长度为1的字符串,然后专门处理它们。因此,将原始查询更改为类似以下内容应该可以:
;WITH cteBench As
(
SELECT *
, CASE
WHEN DataValue IN('-','.','+') THEN '0'
WHEN Len(DataValue) = 1 AND DataValue BETWEEN '0' And '9'
THEN DataValue
WHEN Len(DataValue) = 1 THEN ''
WHEN DataValue LIKE '-%' THEN DataValue
ELSE '0'+DataValue
END As FixedDataValue
FROM dbo.tblBenchmarkData.DataValue
)
SELECT TOP (100) PERCENT cteBench.FieldDataSetID, dbo.tblBC.BCID, CAST(cteBench.FixedDataValue AS float(8)) AS DataValue,
dbo.tblBC.BCMnemonic, dbo.tblDataType.DataTypeMnemonic
FROM dbo.tblFieldDataSet RIGHT OUTER JOIN
cteBench ON dbo.tblFieldDataSet.FieldDataSetID = cteBench.FieldDataSetID LEFT OUTER JOIN
dbo.tblBC LEFT OUTER JOIN
dbo.tblDataType ON dbo.tblBC.DataTypeID = dbo.tblDataType.DataTypeID RIGHT OUTER JOIN
dbo.tblZEGCode ON dbo.tblBC.BCID = dbo.tblZEGCode.BCID ON cteBench.ZEGCodeID = dbo.tblZEGCode.ZEGCodeID
WHERE (dbo.tblDataType.DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}')
AND (dbo.tblFieldDataSet.OriginalFieldDataSetID IS NULL)
AND (dbo.tblFieldDataSet.Duplicate = 0)
AND ISNUMERIC(FixedDataValue) = 1
ORDER BY dbo.tblBC.BCMnemonic, DataValue
出现此问题的原因是,有大量奇数字符串将通过ISNUMERIC()
测试,但无法将CAST()
转换为float(并且仍然可以通过double.TryParse
转换)。我立即知道的三个字符串是:
- “+”
- “.”
- “——”
这里有一种方法可以捕捉其中一些:
SELECT DataValue
FROM dbo.tblBenchData
WHERE ISNUMERIC('0'+DataValue) = 0
奇怪的是,这将正确地转换或无误地拒绝其中大多数:
SELECT CAST('0'+DataValue As float(8)) As DataValue
FROM dbo.tblBenchData
WHERE ISNUMERIC('0'+DataValue) = 0
不过仍然有一些奇怪的案例可以通过
好的,我忘记了这个技巧不喜欢有效的负值
至于“其他”奇怪的情况,我真的记不清它们的全部,也从来没有在任何地方见过它们(我知道,这真的很烦人)。然而,大多数问题字符串都来自不同的数字解析器如何看待所谓的“退化情况”,即单字符字符串
因此,解决这两个问题的一种方法是预先检查长度为1的字符串,然后专门处理它们。因此,将原始查询更改为类似以下内容应该可以:
;WITH cteBench As
(
SELECT *
, CASE
WHEN DataValue IN('-','.','+') THEN '0'
WHEN Len(DataValue) = 1 AND DataValue BETWEEN '0' And '9'
THEN DataValue
WHEN Len(DataValue) = 1 THEN ''
WHEN DataValue LIKE '-%' THEN DataValue
ELSE '0'+DataValue
END As FixedDataValue
FROM dbo.tblBenchmarkData.DataValue
)
SELECT TOP (100) PERCENT cteBench.FieldDataSetID, dbo.tblBC.BCID, CAST(cteBench.FixedDataValue AS float(8)) AS DataValue,
dbo.tblBC.BCMnemonic, dbo.tblDataType.DataTypeMnemonic
FROM dbo.tblFieldDataSet RIGHT OUTER JOIN
cteBench ON dbo.tblFieldDataSet.FieldDataSetID = cteBench.FieldDataSetID LEFT OUTER JOIN
dbo.tblBC LEFT OUTER JOIN
dbo.tblDataType ON dbo.tblBC.DataTypeID = dbo.tblDataType.DataTypeID RIGHT OUTER JOIN
dbo.tblZEGCode ON dbo.tblBC.BCID = dbo.tblZEGCode.BCID ON cteBench.ZEGCodeID = dbo.tblZEGCode.ZEGCodeID
WHERE (dbo.tblDataType.DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}')
AND (dbo.tblFieldDataSet.OriginalFieldDataSetID IS NULL)
AND (dbo.tblFieldDataSet.Duplicate = 0)
AND ISNUMERIC(FixedDataValue) = 1
ORDER BY dbo.tblBC.BCMnemonic, DataValue
上面的SELECT TOP(100%)PERCENT dbo.tblBenchmarkData.FieldDataSetID、dbo.tblBC.BCID…实际上是一个名为qryFieldParameterBCNumericLookup的视图。执行此命令时:
SELECT TOP 100 * FROM MyDatabase.dbo.qryFieldParameterBCNumericLookup
我得到一个错误:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to real.
当我执行这些命令时,它们