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

StackOverflow https://stackoverflow.com/questions/1114549

Вопрос

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

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 передаются в функцию в виде строки, но какие варианты у меня есть?

Это было полезно?

Решение

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

Другие советы

Рассматривали ли вы возможность использования параметризованного запроса?Это решило бы вашу проблему и обеспечило бы дополнительную безопасность в случае, когда 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 <= условия.

Это пахнет уязвимостью 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

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'

В качестве альтернативы, используйте правильное преобразование с правильным код формата, или a пользовательский один, как было предложено 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)

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

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-код столкнется с исключением, ваше соединение не будет закрыто.Возможно, вы захотите добавить немного кода Using, чтобы исправить это.

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top