奇怪的SQL错误(错误)

时间:2013-06-25 09:51:25

标签: sql-server ado.net

所以这真的很奇怪。

我在sqlserver上用.net运行一个带有'Select Count(*)'的sql命令,得到一个像“Needs attention CA”这样的响应(它位于内部连接表的一个记录的一个字段的varchar中)

咦? Count(*)如何返回一个字符串?这段代码正确执行1000次中的999次。有时在某些客户端服务器上,它会抛出一串错误一小时左右才会奇迹般地再次停止。

这是我的sqlcommand:

SELECT Count(*) 
FROM   patientsappointments 
       INNER JOIN appointmenttypes 
               ON patientsappointments.appointmenttypeid = 
                  appointmenttypes.appointmenttypeid 
WHERE  ( ( patientsappointments.date > @WeekStartDate 
           AND patientsappointments.date < @WeekFinishDate ) 
         AND ( patientsappointments.status = 'Pending' ) 
         AND ( patientsappointments.doctorid = @DoctorID ) 
         AND ( appointmenttypes.appointmentname <> 'Note' ) ) 

这些是参数:

@WeekStartDate       = 24/06/2013 12:00:00 AM (DateTime)
@WeekFinishDate      = 1/07/2013 12:00:00 AM (DateTime)
@DoctorID            = 53630c67-3a5a-406f-901c-dbf6b6d1b20f (UniqueIdentifier)

我执行sqlcmd.executescalar来获取结果。有什么想法吗?

实际执行的代码是:

    SyncLock lockRefresh
        Dim WeekFulfilled, WeekPending As Integer
                Using conSLDB As New SqlConnection(modLocalSettings.conSLDBConnectionString)
                    Dim mySQL As SqlCommand
                    mySQL = New SqlCommand("SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID " & _
                                                "WHERE ((PatientsAppointments.Date > @WeekStartDate AND PatientsAppointments.Date < @WeekFinishDate) AND (PatientsAppointments.Status = 'Pending') " & _
                                                "AND (PatientsAppointments.DoctorID = @DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note'))", conSLDB)
                    Try
                        mySQL.Parameters.Add("@WeekStartDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(1)
                        mySQL.Parameters.Add("@WeekFinishDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(8)
                        mySQL.Parameters.Add("@DoctorID", SqlDbType.UniqueIdentifier).Value = cboDoctors.SelectedValue
                        conSLDB.Open()
                        'got errors here like "Conversion from string "R2/3" to type 'Integer' is not valid." Weird.
                        'failing on deadlock - maybe due to simultaneous updating from udp event. Try adding random delay to refresh
                        WeekPending = mySQL.ExecuteScalar
                    Catch ex As Exception
                        ErrorSender.SendError("frmAppointmentBook - RefreshHeader 1", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText), _
                                                                                                        String.Format("mySQL.Parameters: {0}", clsErrorSender.ParamsListToString(mySQL.Parameters))})
                    End Try
                    Me.lblPendingWeek.Text = WeekPending
                    Try
                        mySQL.CommandText = "SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID WHERE " & _
                                                   "(PatientsAppointments.Date > @WeekStartDate AND PatientsAppointments.Date < @WeekFinishDate) AND (PatientsAppointments.Status = 'Fulfilled') AND " & _
                                                   "(PatientsAppointments.DoctorID = @DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note')"
                        'didn't get the error here... but just in case...
                        WeekFulfilled = mySQL.ExecuteScalar
                    Catch ex As Exception
                        ErrorSender.SendError("frmAppointmentBook - RefreshHeader 2", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText)})
                    End Try
                    conSLDB.Close()
                End Using
End SyncLock

确切的错误消息是:

System.InvalidCastException
Conversion from string "Needs Attention DC" to type 'Integer' is not valid.

4 个答案:

答案 0 :(得分:2)

您的问题与代码的COUNT(*)部分无关。问题出在查询中的其他位置。这个特定错误告诉你的是,在某些时候你正在将一个字符字段(它可能通常包含数字)与一个整数字段进行比较。字符字段的值之一恰好是“Needs Attention DC”。如果我不得不猜测它可能是patientsappointments.appointmenttypeidappointmenttypes.appointmenttypeid。仔细检查每个列的数据类型,确保它们实际上是INT。如果它们都是INT,那么请开始检查查询中其他明确命名的列,看看您是否有任何意外。

答案 1 :(得分:1)

您的实施中某处必须出错...

Per the documentation,count始终返回 int 数据类型值。

答案 2 :(得分:0)

我要再做一次猜测。我猜这是一个多线程问题。您可能正在共享多个线程之间的连接。偶尔,线程将从其他地方获取该人并执行它。确保连接变量是本地的,并且一次只能有一个线程访问它。

正如马丁指出的那样,以下答案是错误的。我在这里保留这个以表明这是错误的。

根据每个人的说法,您的列上存在类型不匹配。既然你的where子句似乎没问题,你的联系也没问题,那么它必须在其他地方。我会检查一下患者的预约或预约是否是观点。也许视图有一个抛出异常的连接。检查所有联接的模式定义/位置。在那里的某个地方,你将整数存储在一个字符字段中。这对大多数行都很好,但其中一行有你的字符串。

如果它不在你的视图中,它可能是某个地方的触发器。关键在于某处存在架构不匹配。找到架构不匹配后,可以通过查询该字符串找到该行。

答案 3 :(得分:0)

由于这并不总是发生,因此它必须是发送的其中一个参数值的结果。这是使用动态SQL的lbuiggest问题之一。我要做的是创建动态SQl,然后将其存储在数据库记录表中,其中包含日期和时间以及执行它的用户。然后,当您获得异常时,您可以找到发送的确切SQL代码。您很可能需要对输入变量进行更多控制,以确保放在其中的数据具有正确的数据类型。