问题
I'm trying to read a table where under normal circumstances zero rows will be returned. If any rows are returned an error message is shown. I've tested the SQL statement in on SQL Server and it works. However, I'm getting an error in the DataReader. My code is as follows:
Using sqlConn As SqlConnection = New SqlConnection(cSettings.PrimaryConnectionString)
Dim sSQLc As String = "SELECT * FROM UnitHistory " _
+ "WHERE Unit=" + iUnitID.ToString + " " _
+ "AND StartDate<='" + returnSQLDateString(dAdmissionDateTime) + "' " _
+ "AND (EndDate IS NULL OR " _
+ "EndDate>'" + returnSQLDateString(dAdmissionDateTime) + "') " _
+ "AND IsAmended IS NULL AND IsReversed IS NULL"
Using sqlCMD As SqlCommand = New SqlCommand(sSQLc, sqlConn)
Using sqlR As SqlDataReader = sqlCMD.ExecuteReader ' <--- (The error is raised at this line)
If sqlR.HasRows Then
' if rows were returned then there was someone in the unit
' we're trying to admit to.
MsgBox("There is an admission already in this unit for this admission date")
Exit Sub
End If
End Using
End Using
End Using
A sample SQL Statement which this generates is:
SELECT *
FROM UnitHistory
WHERE Unit=1
AND StartDate<='2019-07-14 20:55'
AND (EndDate IS NULL OR EndDate>'2019-07-14 20:55')
AND IsAmended IS NULL
AND IsReversed IS NULL
The columns in question (as in the SQL Statement) are int/DateTime/DateTime/Bit/Bit
I can't see why this is causing the error to be raised.
回答1:
As you're only using the query to test if there is anything present, perhaps it would make more sense to use a count of the relevant rows.
The using statements can be combined into one, which is sometimes neater. Also, you should always use SQL parameters for SQL queries: that prevents problems with dates, names with apostrophes, and SQL injection attacks - and the query is easier to read.
Dim sql = "SELECT COUNT(*)
FROM UnitHistory
WHERE Unit = @unit
AND StartDate <= @startDate
AND (EndDate IS NULL OR EndDate > @endDate)
AND IsAmended IS NULL
AND IsReversed IS NULL"
Using sqlConn As SqlConnection = New SqlConnection(cSettings.PrimaryConnectionString),
cmd As New SqlCommand(sql, sqlConn)
cmd.Parameters.Add("@unit", SqlDbType.Int).Value = iUnitID
cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = dAdmissionDateTime
cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = dAdmissionDateTime
sqlConn.Open()
Dim admissionCount = CInt(cmd.ExecuteScalar())
If admissionCount > 0 Then
' if rows were returned then there was someone in the unit
' we're trying to admit to.
MsgBox("There is an admission already in this unit for this admission date.")
Exit Sub
End If
End Using
(If your copy of Visual Studio doesn't like the multi-line string for sql, just put it all on one line.)
回答2:
I went to SQL Management studio and tried a similar query on one of my tables and it quickly pointed out the problem. It wanted additional parentheses.
Using sqlConn As SqlConnection = New SqlConnection(cSettings.PrimaryConnectionString)
Dim sSQLc As String = "SELECT * FROM UnitHistory " _
+ "WHERE (Unit=" + iUnitID.ToString + ") " _
+ "AND (StartDate<='" + returnSQLDateString(dAdmissionDateTime) + "') " _
+ "AND ((EndDate IS NULL) OR " _
+ "(EndDate>'" + returnSQLDateString(dAdmissionDateTime) + "')) " _
+ "AND (IsAmended IS NULL) AND (IsReversed IS NULL)"
Using sqlCMD As SqlCommand = New SqlCommand(sSQLc, sqlConn)
Using sqlR As SqlDataReader = sqlCMD.ExecuteReader ' <--- (The error is raised at this line)
If sqlR.HasRows Then
' if rows were returned then there was someone in the unit
' we're trying to admit to.
MsgBox("There is an admission already in this unit for this admission date")
Exit Sub
End If
End Using
End Using
End Using
来源:https://stackoverflow.com/questions/60243785/sql-datareader-giving-string-or-binary-data-will-be-truncated