Madhu Chatterjee Ответов: 3

Предложение Group by не работает в combobox


Когда я нажимаю на поле со списком в событии загрузки формы, никакие данные не отображаются в поле со списком.

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

Я пишу метод ниже и вызываю его в событии загрузки формы, но мое поле со списком не показывает никаких элементов..
У меня есть две таблицы в моей базе данных sql с именами Faculty и Attn.

Private Sub Load_Faculty()
        Dim cn As New OleDb.OleDbConnection(cnSettings2)
        Dim cmd As New OleDb.OleDbCommand
        Dim reader As OleDb.OleDbDataReader
        Try
            cn.Open()
            Dim sql As String
            sql = "Select Faculty from Faculty,Attn where Faculty.Fac_Id =Attn.Fac_Id and Attn.ForMnth ='" & CmbMnth.Text & "' and Attn.ForYr ='" & TxtYear.Text & "' group by Faculty"
            cmd = New OleDb.OleDbCommand(sql, cn)
            reader = cmd.ExecuteReader
            While reader.Read
                Dim id = reader.Item("Faculty")
                CmbFac.Items.Add(id)
            End While
            cn.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Richard MacCutchan

Используйте свой отладчик, чтобы выяснить, действительно ли вы извлекаете какие - либо данные из базы данных.

Madhu Chatterjee

Я заметил, что проблема, но не в состоянии решить...
Проблема заключается в CmbMnth.Текст и TxtYear.Текст когда я помещаю значения этих двух в свой quiery, он не показывает никаких данных в поле со списком.

Richard MacCutchan

Прекратите гадать и посмотрите на фактические значения, которые вы пытаетесь использовать в SQL-запросе. Что это за ценности, и почему они не дают никаких результатов?

Madhu Chatterjee

Если CmbMnth.Text = "февраль" и TxtYear.Text="2020" тогда
поле со списком заполняется именами преподавателей.

Richard MacCutchan

Пожалуйста, прочтите мое предыдущее сообщение еще раз. Каковы фактические значения, которые вы получаете от CmbMnth.Text и TxtYear.Text Каковы фактические записи, возвращаемые из базы данных? Вы никогда не решите эту проблему, если не выясните, что все эти пункты являются, и проходят ли они ваши тесты на равенство.

3 Ответов

Рейтинг:
2

Patrice T

Цитата:
Когда я нажимаю на поле со списком в событии загрузки формы, никакие данные не отображаются в поле со списком.

Ваш код ведет себя не так, как вы ожидаете, или вы не понимаете, почему !

Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что должен делать ваш код, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик - Википедия, свободная энциклопедия[^]

Visual Basic / Visual Studio Video Tutorial - Базовая Отладка - YouTube[^]
Visual Basic .NET programming for Beginners - точки останова и средства отладки[^]

Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.
-----
sql = "Select Faculty from Faculty,Attn where Faculty.Fac_Id =Attn.Fac_Id and Attn.ForMnth ='" & CmbMnth.Text & "' and Attn.ForYr ='" & TxtYear.Text & "' group by Faculty"

Не обязательно решение вашего вопроса, но у вас есть еще одна проблема.
Никогда не создавайте SQL-запрос путем объединения строк. Рано или поздно вы сделаете это с помощью пользовательских вводов, и это откроет дверь к уязвимости под названием "SQL-инъекция", она опасна для вашей базы данных и подвержена ошибкам.
Одна кавычка в имени - и ваша программа выйдет из строя. Если пользователь вводит имя, например "Брайан О'Коннер", может привести к сбою вашего приложения, это уязвимость SQL-инъекции, и сбой-это наименьшая из проблем, вредоносный пользовательский ввод, и он продвигается к командам SQL со всеми учетными данными.
SQL-инъекция - Википедия[^]
SQL-инъекция[^]
Атаки SQL-инъекций на примере[^]
PHP: SQL-инъекция - руководство пользователя[^]
Шпаргалка по предотвращению инъекций SQL - OWASP[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? - Обмен Стеками Информационной Безопасности[^]


Maciej Los

5ed!

Patrice T

Спасибо

Рейтинг:
1

OriginalGriff

Дон;т сделать это, как это! Никогда не объединяйте строки для построения команды 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;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

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

И когда вы исправите это, хотя вся ваша БД, откройте SSMS и попробуйте свой запрос там: я предполагаю, что он не возвращает никаких совпадающих строк - я подозреваю, что вам нужно соединение там, чтобы "объединить" две таблицы, а не просто пытаться "скрепить их вместе" и надеяться, что это сработает, - но без ваших таблиц и данных мы не можем быть более точными.


Maciej Los

5ed!

Рейтинг:
1

Maciej Los

Прежде всего, вы должны следовать инструкциям, данным моими коллегами.

Теперь взгляните на свою команду sql:

sql = "Select Faculty from Faculty,Attn where Faculty.Fac_Id =Attn.Fac_Id and Attn.ForMnth ='" & CmbMnth.Text & "' and Attn.ForYr ='" & TxtYear.Text & "' group by Faculty"


Записи:
1)
Если ForMnth и ForYr поле имеет тип числовой, то ['] вокруг излишне.

2)
Нет статистическая функция[^], так группа по[^] оговорка излишня.

3)
Если вы хотите получить уникальные значения Faculty поле, которое вы должны использовать ОТЧЕТЛИВЫЙ[^]

В наши дни вы должны использовать JOINс объединения данных из множества таблиц. Один ГДЕ[^] оператор должен быть использован для добавления условия. Видеть: Визуальное представление SQL-соединений[^]

Наконец, я бы предложил использовать Оператор using[^].

Почему?
Цитата:
Иногда коду требуется неуправляемый ресурс, например дескриптор файла, оболочка COM или соединение SQL. Блок Using гарантирует удаление одного или нескольких таких ресурсов, когда ваш код закончит с ними. Это делает их доступными для использования другим кодом.

Управляемые ресурсы удаляются сборщиком мусора .NET Framework (GC) без какого-либо дополнительного кодирования с вашей стороны. Вам не нужен блок Using для управляемых ресурсов. Однако вы все равно можете использовать блок Using для принудительного удаления управляемого ресурса вместо ожидания сборщика мусора.


Видеть:
Try
    Dim sConn As String = "your_connectionString_here;"
    Dim oRdr As OleDbDataReader
    Dim dt As DataTable = New DataTable()
    Dim pMonth As Integer = 17
    Dim pYear As Integer = 02

    Using oConn As OleDbConnection = New OleDbConnection(sConn)
        oConn.Open()
        Using oComm AS OleDbCommand = New OleDbCommand()
            oComm.Connection = oConn
            oComm.CommandType = CommandType.Text
            oComm.CommandText =  "SELECT DISTINCT Faculty FROM Faculty F INNER JOIN Attn AS A ON F.Fac_Id = A.Fac_Id WHERE A.ForMnth = @pMonth AND A.ForYr = @pYear;"
            oComm.Parameters.AddWithValue("@pMonth", pMonth)
            oComm.Parameters.AddWithValue("@pYear", pYear)
            oComm.ExecuteNonQuery()
            oRdr = oComm.ExecuteReader()
            dt.Load(oRdr)
        End Using
        oConn.Close()
    End Using

    //now you can use Datatable object!

Catch ex As OleDbException
    Console.WriteLine(ex.Message)

Catch ex As Exception
    Console.WriteLine(ex.Message)

End Try