Преобразование не удалось при преобразовании даты и времени из строки символов - PullRequest
1 голос
/ 12 июля 2009

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

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

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

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

Ответы [ 5 ]

2 голосов
/ 12 июля 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
2 голосов
/ 12 июля 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 <=.

1 голос
/ 12 июля 2009

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

1 голос
/ 12 июля 2009

11/7/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)
0 голосов
/ 12 июля 2009

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

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
...