2013-06-25 120 views
0

所以这真的很奇怪。奇怪的SQL错误(Bug)

我在sqlserver上运行一个带有'Select Count(*)'的.net命令,得到一个类似于“需要注意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. 
+1

.NET应用程序正在执行不同于预期的'SQL'部分。或者在你的程序/函数中,另一个'SELECT'语句在'COUNT'之后执行。在管理工作室运行声明,你会得到什么? –

+2

什么是**确切**错误信息? ''需要注意CA“'不是SQL Server错误消息。 –

+0

@MartinSmith - 我不认为有错误信息。 SQL正在返回不同于预期的输出。 –

回答

1

您必须在某个地方执行有错误...

Per the documentation,总是指望返回一个int数据类型值。

+0

你会想!我添加了失败的确切代码(偶尔和仅在生产中,然后才有时)。错误被捕获到,因此没有其他命令或存储过程参与。 – RichieRich

+0

您是否正在重用mySQL var来运行其他查询? WeekPending var的类型是什么? –

+0

另外,请检查这些列的数据类型(patientsappointments.appointmenttypeid,appointmenttypes.appointmenttypeid) –

2

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

+1

不,这不是这种情况。错误是一个'.NET'错误('System.InvalidCastException')而不是一个SQL Server错误(当将varchar值'xyz'转换为数据类型int.'时,转换失败并引发为'SqlException'。 –

+0

有时结果将是来自连接表中同一字段的另一个字符串:AppointmentTypes.AppointmentName。您会注意到字段确实出现在WHERE子句中,它看起来非常随意,ID字段都是sql uniqueidentifiers,not int – RichieRich

+0

这些参数的值是肯定的,因为错误发送者从SqlCommand中获取它们(并且在1000次中有999次它完全按预期工作) – RichieRich

0

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

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

从大家已经说过的话,你的专栏有一个类型不匹配。由于你的where子句看起来很好,而且你的连接没有问题,所以它必须在其他地方。我会检查是否患者预约或预约类型是意见。也许视图有一个引发异常的连接。检查所有连接/哪里的模式定义。在那里的某个地方,你将整数存储在一个字符字段中。大多数行都很好,但其中一个有你的字符串。

如果它不在您的视图中,它可能是某处的触发器。重点在于某处存在模式不匹配。一旦发现模式不匹配,您可以通过查询该字符串来查找该行。

+0

这会引发'SqlException'而不是'System .InvalidCastException'。不存在'SELECT'触发器。 –

+0

@MartinSmith好点。 –

+0

如果有帮助,表格只是表格;没有视图。 – RichieRich

0

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

+0

我的确如此。事实上,在catch块中,每当发生命令文本和参数错误时,我都会发送一封电子邮件。问题中显示的sql命令和参数将从错误电子邮件中剪切并直接粘贴。但是,不友好的参数会导致sql错误,不会返回不能放入整数的字符串。 – RichieRich