Arnav121 Ответов: 2

Как найти между двумя датами, такими как 01 мая 2018 года и 25 мая 2018 года?


Когда я фильтрую дату, как 01-May-2018 до 31-May-2018, то результат показывает май месяц завершен, но его показывают другие месяцы дата, как 02-Apr-2018 и все даты в 01to31 в datagridview.

мне приходится искать только месяц за месяцем.

его шоу выглядит так

02-Апр-2018
03-Апр-2018
01-май-2018
08-май-2018
10-май-2018
12-май-2018
31-май-2018
15-Jun-2018
28 июня 2018 года
?????

Что я уже пробовал:

<pre> Private Function GetRows() As DataTable
        Dim DateStr As DateTime = DateTimePicker1.Value.Date
        Dim DateEnd As DateTime = DateTimePicker2.Value.Date

        Dim dtable As DataTable = New DataTable
        Dim con1 As OleDbConnection
        '  Try
        con1 = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Application.StartupPath & "\WB001.mdb;Jet OLEDB:Database Password=jhk312;")

        Using cmd1 As OleDbCommand = New OleDbCommand("SELECT * FROM DW1 WHERE Date BETWEEN #" & DateStr.ToString & "# And #" & DateEnd.ToString & "#", con1)
            ' With cmd1.Parameters
            '.Add("@dt1", OleDbType.Date).Value = DateTimePicker1.Value
            ' .Add("@dt2", OleDbType.Date).Value = DateTimePicker2.Value
            ' End With
            Dim adp As New OleDbDataAdapter(cmd1)
            ' con1.Open()
            adp.Fill(dtable)
            DataGridView1.DataSource = dtable
            con1.Close()
            'End Using

        End Using




        ' Catch ex As Exception
        'MsgBox("Error")

        '  End Try
    End Function

Richard Deeming

НИКОГДА используйте конкатенацию строк для построения SQL-запроса. ВСЕГДА используйте параметризованный запрос.

Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов | OWASP[^]

Using cmd1 As OleDbCommand = New OleDbCommand("SELECT * FROM DW1 WHERE Date BETWEEN ? And ?", con1)
    cmd1.Parameters.AddWithValue("p1", DateStr)
    cmd1.Parameters.AddWithValue("p2", DateEnd)

Richard Deeming

Вы можете упростить строку подключения:

con1 = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\WB001.mdb;Jet OLEDB:Database Password=jhk312;")

По умолчанию, |DataDirectory| всегда будет указывать на папку приложения для приложений Windows, и App_Data папка для ASP.NET приложения.

Однако вы должны быть осторожны, если ваше приложение будет развернуто в папке "Program Files". Обычные пользователи не имеют прав на запись в файлы по этому пути, поэтому ваше приложение не сможет использовать базу данных Access, хранящуюся в каталоге приложения. Видеть Где я должен хранить свои данные?[^] для получения дополнительной информации.

Richard Deeming

Какой тип данных у вас есть Date столбец определяется как? Это звучит так, как будто он хранится в виде строки, а не реальной даты.

Arnav121

у меня есть сохраненные столбцы даты, тип данных-текст.

Arnav121

Итак, вы говорите, что приложение Startpath удалить и ввести там |DataDirectory| ??????

Arnav121

Тхнакс снова за помощью после смены своей работы велик.

2 Ответов

Рейтинг:
20

OriginalGriff

Наиболее вероятная причина-плохой дизайн в вашей БД. судя по показанным вами значениям, ваш столбец даты в БД-это VARCHAR или NVARCHAR, а не дата.
Когда вы это сделаете, ваши сравнения для дат будут строковыми сравнениями, что означает, что все сравнение основано на первом различном символе в двух строках. Никакие другие символы не проверяются.
Это означает, что порядок сортировки для "нормальных intgers" становится:

1
10
11
...
19
2
20
21
...
29
3
30
...
И очень похожий порядок сортировки происходит с датами.
Решение простое: измените дизайн БД и всегда храните значения в соответствующих типах данных. Целочисленные значения int INT, плавающая точка в FLOAT или DECIMAL, даты в DATE или DATETIME. Если вы этого не сделаете, то получите хлопоты каждый раз, когда попытаетесь их использовать...

И как сказал Ричард: никогда не объединяйте строки для построения SQL-команды. Это оставляет вас широко открытыми для случайной или преднамеренной атаки SQL-инъекции, которая может уничтожить всю вашу базу данных. Вместо этого всегда используйте параметризованные запросы.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?


Arnav121

является ли мой код правильным или нет?
и мой тип данных столбца даты-текст.

OriginalGriff

И это ваша проблема. Сравнение строк выполняется с помощью сравнения строк, а не дат.

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

Arnav121

я могу изменить текст типа данных на дату/время, и теперь он отлично работает.
вами человек за помощью оригинальных Грифф и Ричард считая.

OriginalGriff

Всегда пожалуйста!

Рейтинг:
0

Maciej Los

Как OriginalGriff[^] уже упоминалось, что вы должны измениться Date поле для соответствующего типа данных. Примечание: вам также нужно изменить его название, потому что Date является зарезервированное слово[^] для MS Access. Использование зарезервированных слов может вызвать несколько проблем...

Как изменить тип данных?
1. откройте базу данных в эксклюзивный режим[^]
2. Откройте DW таблица в режиме проектирования
3. Добавьте новое поле, например: DateOfEvent и выберите Date тип данных (разрешить значения null)
4. сохраните изменения и закройте DW стол
5. Создайте новый запрос и выполните его:

UPDATE DW SET DateOfEvent = CDate(Date)

6. Если обновление прошло успешно, вы можете удалить его Date поле

Ну, соответственно к Ричард Диминг[^] комментарий о том, что SQL-инъекция[^], вы должны использовать параметризованные запросы вместо сцепленных строк:

Похоже, вы были довольно близки к правильному решению. Вот "улучшенная" версия вашего кода:
Dim sCon As String = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}\WB001.mdb;Jet OLEDB:Database Password=jhk312;", Application.StartupPath)
Dim sSql As String = "SELECT * FROM DW1 WHERE DateOfEvent BETWEEN @dt1 And @dt2;"

Using con1 As OleDbConnection = New OleDbConnection(sCon)
	con1.Open()
	Using cmd1 As OleDbCommand = New OleDbCommand(sSql, con1)
	    With cmd1.Parameters
		    .Add("@dt1", OleDbType.Date).Value = DateTimePicker1.Value
		    .Add("@dt2", OleDbType.Date).Value = DateTimePicker2.Value
	    End With
	    Dim adp As New OleDbDataAdapter(cmd1)
	    adp.Fill(dtable)
	    DataGridView1.DataSource = dtable
	End Using
    con1.Close()
End Using


Примечание: Даже если официальная документация утверждает, что поставщик OleDb не позволяет использовать именованные параметры, вы можете использовать их, но есть одно требование: вы должны добавлять параметры в том же порядке, что и их порядок в инструкции sql. ;)


Richard Deeming

"... вы должны добавить параметры в том же порядке, что и их порядок в sql-операторе."

Значит, на самом деле они не называются параметрами. :)

Maciej Los

Ты меня туда загнал! :смеяться:
Это всего лишь семантика ;)

Member 13890537

Спасибо тебе, Мацей Лос. Я узнал о тебе кое-что очень важное.

Maciej Los

Всегда пожалуйста.

Arnav121

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

Maciej Los

Всегда пожалуйста.