Ошибка преобразования при преобразовании даты и времени из символьной строки

Строка, переданная моей пользовательской функции, выглядит следующим образом:

SELECT key FROM ubis WHERE MemberID = '144'
AND To >='11/7/2009 9:11:23 pm'
AND From <= '11/7/2009 9:11:23 pm'

    Public Shared Function GetDataTable(ByVal CmdText As String) As DataTable
        Dim myConn As New SqlConnection(ConfigurationManager.ConnectionStrings("Conn").ConnectionString)
        Dim myCmd As New SqlCommand(CmdText, myConn)
        myConn.Open()
        Dim myReader As SqlDataReader = myCmd.ExecuteReader()
        Dim myTable As New DataTable()
        myTable.Load(myReader)
        myConn.Close()
        Return (myTable)
    End Function

и вот ошибка, которую я получаю, Преобразование не удалось при преобразовании даты и времени из символьной строки

Я понимаю, что поля даты и времени передаются в функцию как строка, но какие у меня есть варианты?


person OrElse    schedule 11.07.2009    source источник


Ответы (5)


Вы пытались запустить sql в студии управления и посмотреть, что произойдет?

person Nick DeMayo    schedule 11.07.2009
comment
Visual Studio передавала дату и время на греческом языке (pm было отправлено как «μμ») - person OrElse; 12.07.2009

Рассматривали ли вы возможность использования параметризованного запроса? Это решит вашу проблему и обеспечит дополнительную безопасность в случае, когда условия WHERE берутся из пользовательского ввода.

Пример (VB.NET):

Dim myCmd As New SqlCommand(CmdText, myConn)
myCmd.Parameters.AddWithValue("MemberID", 144)
myCmd.Parameters.AddWithValue("Timestamp", DateTime.Now)

Используется с этим текстом запроса (SQL):

SELECT key FROM ubis WHERE MemberID = @MemberID
AND @Timestamp BETWEEN From AND To

Не по теме: ключевое слово BETWEEN в SQL — это просто изящный способ выразить условия >= AND <=.

person Jørn Schou-Rode    schedule 11.07.2009

Это пахнет уязвимостью SQL-инъекций. Эта дата случайно не исходила от пользователя (даже косвенно), не так ли? Даже если это безопасно, общие функции, такие как GetDataTable(), которые не учитывают хорошие параметры запроса, почти всегда являются ошибкой.

Вы хотите что-то еще вроде этого:

Public Shared Function GetMemberKeys(ByVal MemberID As Integer, ByVal KeyDate As DateTime) As DataTable

    Static sql As String= _
         "SELECT key" _
      + " FROM ubis" _ 
      + " WHERE MemberID= @MemberID AND @KeyDate BETWEEN [FROM] AND [TO]"

    Dim dt As New DataTable()
    Using cn As New SqlConnection(ConfigurationManager.ConnectionStrings("Conn").ConnectionString), _
          cmd As New SqlCommand(sql, cn)

        cmd.Parameters.Add("@MemberID", SqlDbType.Int).Value = MemberID
        cmd.Parameters.Add("@KeyDate", SqlDbType.DateTime).Value = KeyDate

        cn.Open()
        Using rdr As SqlDataReader = cmd.ExecuteReader()
             dt.Load(rdr)
        End Using
    End Using
    Return dt
End Function
person Joel Coehoorn    schedule 11.07.2009

07.11.2009 неоднозначно - это 11 июля или 7 ноября?

SQL не может сказать - и это зависит от настроек по умолчанию, с которыми он был настроен. Дату лучше передавать в однозначном формате:

SELECT key FROM ubis WHERE MemberID = '144' 
               AND To >='11 July 2009 9:11:23 pm' 
               AND From <= '11 July 2009 9:11:23 pm'

В качестве альтернативы используйте правильное преобразование с правильным кодом формата, или пользовательский, предложенный Zyphrax:

SELECT key FROM ubis WHERE MemberID = '144'
       AND To >= CONVERT(datetime, '11/7/2009 9:11:23 pm', 105)
       AND From <= CONVERT(datetime, '11/7/2009 9:11:23 pm', 105)
person Oded    schedule 11.07.2009
comment
11 июля в греческом формате! дд/мм/гггг - person OrElse; 12.07.2009
comment
Если ваш SQL-сервер настроен на даты в США, он будет интерпретировать дату как 7 октября. - person Oded; 12.07.2009

Вы можете использовать команду CONVERT, чтобы преобразовать char в дату и время.

SELECT key FROM ubis WHERE MemberID = '144'
           AND To >= CONVERT(datetime, '11/7/2009 9:11:23 pm', 105)
           AND From <= CONVERT(datetime, '11/7/2009 9:11:23 pm', 105)

Я не уверен насчет 105, вам может понадобиться Google для правильного кода формата.

Кроме того, если ваш код SQL столкнется с исключением, ваше соединение не будет закрыто. Возможно, вы захотите добавить немного кода использования, чтобы исправить это.

Public Shared Function GetDataTable(ByVal CmdText As String) As DataTable        
 Using myConn As New SqlConnection(ConfigurationManager.ConnectionStrings("Conn").ConnectionString)
   Using myCmd As New SqlCommand(CmdTxt, myConn)
     conn.Open()
       Using myReader As SqlDataReader = myCmd.ExecuteReader()
           Dim myTable As New DataTable()
           myTable.Load(myReader)
           myConn.Close()
           Return (myTable)  
      End Using
     End Using
End Function
person Zyphrax    schedule 11.07.2009