在我的存储过程中,我有一个case语句,它应该测试一个字段是否为数字并处理该字段,但无论如何都会得到相同的错误。我试过以下:
CASE WHEN ISNUMERIC(subScores.ScoreValue) = 1 THEN CAST(subScores.ScoreValue AS REAL) ELSE -1 END
我还使用了自定义转换功能,因为我读过isnumeric并非100%可靠但收到了同样的错误。我也试过使用CONVERT
但没有成功。我甚至用0=1
取代了isnumeric,它应该总是失败,但我仍然得到同样的错误,我发现它真的很奇怪。这是我的错误:
Error converting data type nvarchar to real
它正在检查的值如下:
A0, A10, A23, B9, B51, C90, C100, etc
对此行为的任何想法?
这是完整的程序。问题发生在THEN
之后的where子句中的第一种情况,而不是使用实际字段使用-1。它还包含我对ISNUMERIC和我的自定义函数的使用:
@strDemoCodeIds nvarchar(100),
@strYearIds nvarchar(100),
@intRosterSetId int,
@intSchoolId int,
@intTeachId int,
@intGradeId int,
@intDeptId int,
@intCourseId int,
@intPeriodId int,
@strTestInstIds nvarchar(100),
@intTestTypeId int,
@intSubjectId int,
@intScoreTypeId int,
@strSuppScoreTypeId nvarchar(20),
@intClusterScoreTypeId int,
@intClusterColorScoreTypeId int,
@intLocalReportId int,
@strSortMethod nvarchar(20),
@intAnchorYear int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @topYearID INT
DECLARE @subs TABLE (subId int)
IF @intSubjectId < 100
BEGIN
INSERT INTO @subs
SELECT MM_Test_Subjects.pkTestSubjectID
FROM MM_Test_Subjects
WHERE MM_Test_Subjects.fkCSTStrandID = @intSubjectId
END
ELSE
BEGIN
INSERT INTO @subs VALUES (@intSubjectId)
END
DECLARE @years TABLE (yearId int)
INSERT INTO @years
SELECT number FROM itot(@strYearIds, N',')
SET @topYearID = @intAnchorYear
SELECT s.pkStudentID,
s.LastName,
s.FirstName,
s.StudentNumber,
st.fkTestInstanceID,
bands.Description AS 'PL',
bands.Color,
subScoresSupp.scoreValue AS 'SuppScore',
clusters.pkTestClusterID,
clusterScores.ScoreValue,
colors.ScoreValue,
ti.TestInstanceName,
tp.TestPeriodTitle,
subScores.ScoreValue AS 'PLScore',
ScoreType.pkScoreTypeID,
bands.StackPosition AS 'StackPosition'
FROM Students s
INNER JOIN StudentTests st ON s.pkStudentID = st.fkStudentID
INNER JOIN StudentTests baseSt ON s.pkStudentID = baseSt.fkStudentID
AND baseSt.fkGradeID = CASE @intGradeId WHEN 99 THEN baseSt.fkGradeID ELSE @intGradeId END
AND EXISTS (SELECT * FROM StudentScores_Subject baseSubScores WHERE baseSubScores.fkStudentTestID = baseSt.pkStudentTestID
AND baseSubScores.fkTest_SubjectID IN (SELECT subId FROM @subs)
AND baseSubScores.fkScoreTypeID = @intScoreTypeId)
INNER JOIN StudentTestDemographics d ON d.fkStudentTestID = baseSt.pkStudentTestID
INNER JOIN itot(@strDemoCodeIds, N',') tblDemoCodes ON d.fkDemographicCodeID = CASE @strDemoCodeIds WHEN '0' THEN d.fkDemographicCodeID ELSE tblDemoCodes.number END
INNER JOIN StudentScores_Subject subScores ON subScores.fkStudentTestID = st.pkStudentTestID
AND subScores.fkTest_SubjectID IN (SELECT subId FROM @subs)
AND subScores.fkScoreTypeID = @intScoreTypeId
LEFT JOIN PerformanceLevelReportBands bands ON bands.fkPerformanceLevelReportID = @intLocalReportId
LEFT JOIN MMARS_Web_TestInfo_California.dbo.PerfLevelReportBandCutScores cutScores ON cutScores.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
AND cutScores.fkGradeID = @intGradeId
AND cutScores.fkTestSubjectID IN (SELECT subId FROM @subs)
RIGHT JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
LEFT JOIN StudentScores_Subject subScoresSupp ON subScoresSupp.fkStudentTestID = st.pkStudentTestID
AND subScoresSupp.fkTest_SubjectID IN (SELECT subId FROM @subs)
AND subScoresSupp.fkScoreTypeID IN (SELECT tblsubScoresSupp.number FROM itot(@strSuppScoreTypeId, N',') tblsubScoresSupp)
LEFT JOIN MM_ScoreTypes ScoreType ON ScoreType.pkScoreTypeID = subScoresSupp.fkScoreTypeID
LEFT JOIN StudentScores_Cluster clusterScores ON clusterScores.fkStudentTestID = st.pkStudentTestID
AND clusterScores.fkTest_SubjectID IN (SELECT subId FROM @subs)
AND clusterScores.fkScoreTypeID = @intClusterScoreTypeId
LEFT JOIN StudentScores_Cluster colors ON colors.fkStudentTestID = st.pkStudentTestID
AND colors.fkTest_SubjectID IN (SELECT subId FROM @subs)
AND colors.fkScoreTypeID = @intClusterColorScoreTypeId
AND colors.fkTest_ClusterID = clusterScores.fkTest_ClusterID
LEFT JOIN MM_Test_Clusters clusters ON clusters.pkTestClusterID = clusterScores.fkTest_ClusterID
INNER JOIN TestInstances ti ON ti.pkTestInstanceID = st.fkTestInstanceID
INNER JOIN TestInstances baseTi ON baseTi.pkTestInstanceID = baseSt.fkTestInstanceID
AND baseTi.fkSchoolYearID = @topYearID
INNER JOIN CAHSEE_TestPeriods tp on tp.pkTestPeriodID = ti.fkTestPeriodID
INNER JOIN CAHSEE_TestPeriods baseTp on baseTp.pkTestPeriodID = baseTi.fkTestPeriodID
INNER JOIN Roster_Students rs ON rs.fkStudentID = s.pkStudentID
INNER JOIN Roster_Groups rg ON rg.fkTestInstanceID = baseTi.pkTestInstanceID
AND ti.pkTestInstanceID IN (SELECT tblTestInstances.number FROM itot(@strTestInstIds, N',') tblTestInstances)
AND baseTi.pkTestInstanceID IN (SELECT tblTestInstances.number FROM itot(@strTestInstIds, N',') tblTestInstances)
AND rg.fkRosterSetID = @intRosterSetId
AND rg.pkRosterGroupID = rs.fkRosterGroupID
AND (rg.fkSchoolID = @intSchoolId OR @intSchoolId = 0)
AND (rg.fkTeacherID = @intTeachId OR @intTeachId = 0)
AND (rg.fkGradeID = baseSt.fkGradeID)
AND (rg.fkDepartmentID = @intDeptId OR @intDeptId = 0)
AND (rg.fkCourseID = @intCourseId OR @intCourseId = 0)
AND (rg.fkPeriodID = @intPeriodId OR @intPeriodId = 0)
WHERE (bandComponents.ScoreValue = subScores.ScoreValue)
OR
((CASE WHEN ISNUMERIC(subScores.ScoreValue) = 1 THEN CAST(subScores.ScoreValue AS REAL) ELSE subScores.ScoreValue END)
BETWEEN (CASE WHEN dbo.TryConvertInt(bandComponents.minScore) = 1 THEN CAST(bandComponents.minScore AS REAL) ELSE bandComponents.minScore END) and
(CASE WHEN dbo.TryConvertInt(bandComponents.maxScore) = 1 THEN CAST(bandComponents.maxScore AS REAL) ELSE bandComponents.maxScore END)/*CAST(ISNULL(bandComponents.maxScore,'0') AS INT)*/)
OR
((CASE WHEN ISNUMERIC(subScores.ScoreValue) = 1 THEN CAST(subScores.ScoreValue AS REAL) ELSE -1 END)
BETWEEN ISNULL(cutScores.minScore,0) and ISNULL(cutScores.maxScore,0))
GROUP BY s.pkStudentID, s.LastName, s.FirstName, s.StudentNumber, st.fkTestInstanceID, bands.Description, bands.Color, subScoresSupp.scoreValue,
clusters.pkTestClusterID, clusterScores.ScoreValue, colors.ScoreValue, ti.TestInstanceName, tp.TestPeriodTitle, subScores.ScoreValue,
ScoreType.pkScoreTypeID, bands.StackPosition
ORDER BY
CASE WHEN @strSortMethod = 'ScoreDesc'
THEN bands.StackPosition END DESC,
CASE WHEN @strSortMethod = 'ScoreAsc'
THEN bands.StackPosition END ASC,
CASE WHEN @strSortMethod = 'ScoreDesc' AND ISNUMERIC(subScores.ScoreValue) = 1
THEN CONVERT(int, subScores.ScoreValue) END DESC,
CASE WHEN @strSortMethod = 'ScoreAsc' AND ISNUMERIC(subScores.ScoreValue) = 1
THEN CONVERT(int, subScores.ScoreValue) END ASC,
s.LastName, s.FirstName, s.pkStudentID, st.fkTestInstanceID
END
答案 0 :(得分:0)
我会尝试你的东西,然后找到这个问题
select CASE WHEN ISNUMERIC(CONVERT(nvarchar,'- 5')) = 1 THEN CAST(CONVERT(nvarchar,'- 5') AS REAL) ELSE -1 END
Isnumeric函数应返回此值为true,并且convert函数不应将值转换为real,因为值为空格。
在列中查找此类型的数据,例如得分值。
答案 1 :(得分:0)
/*Show how isnumeric differs from TRY_CONVERT*/
declare @temp table (dec int, chr char(1) , isnum int,tryconvert int)
declare @loop int = 1
declare @i int
while @loop < 127
begin
set @i = @loop
insert into @temp (dec,chr,isnum,tryconvert)
select @i,char(@i) charac, isnumeric(char(@i)), TRY_CONVERT(int,char(@i))
set @loop = @loop + 1
end
select * from @temp where isnum = 1
答案 2 :(得分:0)
问题不在于您指向的行!
这一行没问题:
CASE WHEN ISNUMERIC(subScores.ScoreValue) = 1 THEN CAST(subScores.ScoreValue AS REAL) ELSE -1 END
但是在第一种情况下,就在WHERE
子句后面就有了这一行
CASE WHEN ISNUMERIC(subScores.ScoreValue) = 1 THEN CAST(subScores.ScoreValue AS REAL) ELSE subScores.ScoreValue END
它不能像ScoreValue
不是数字一样工作,你有一个真实数据和varchar数据的情况(我猜ScoreValue
是varchar)
您必须再次使用-1
代替ScoreValue
才能使其正常工作