2013-06-25 119 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