Динамический SQL-запрос с VB.net Переменные Строковое условие

#sql #vb.net

#sql #vb.net

Вопрос:

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

У меня есть 4 строки, если условие строки не равно нулю или пусто, я добавляю его в запрос, но первое всегда будет не нужно, И поэтому я добавил, ГДЕ 1 = 1, затем я могу добавить И ID = @ID и т.д., Чтобы можно было добавить все четыре. Чего мне не хватает?

    Dim sqlBuilder As New StringBuilder()
    '1 = 1 allows an and.
    sqlBuilder.Append("SELECT * FROM table WHERE 1=1 ")

    If Surname <> "" Then
        sqlBuilder.Append(" AND Surname=@surname")
    End If
    If Payroll <> "" Then
        sqlBuilder.Append(" AND payroll = @payroll")
    End If
    If VehicleReg <> "" Then
        sqlBuilder.Append(" AND registration = @registration")
    End If
    If OrgID > 0 Then
        sqlBuilder.Append(" AND OrganisationID = @orgid")
    End If
 

Комментарии:

1. Вы получаете сообщение об ошибке? Если да, то что это?

2. То, что вы делаете, кажется мне прекрасным, но единственное, что я бы предложил, это проверить длину вашего конструктора, а затем добавить только «И», если требуется

3. Ошибки нет, мне просто интересно, есть ли лучший способ.

4. Лично я бы придерживался этого (или какой-либо другой цепочки, построенной на LINQ), а не одного «запроса бога». Почему, смотрите в моем комментарии к ответу @jmcilhinney.

Ответ №1:

Существует простой способ использовать один неизменяемый SQL-запрос, делая параметры необязательными, например

 Dim query = "SELECT * FROM Person WHERE (@FirstName IS NULL OR FirstName = @FirstName) AND (@LastName IS NULL OR LastName = @LastName)"
Dim command As New SqlCommand

command.CommandText = query

With command.Parameters
    .Add("@FirstName", SqlDbType.VarChar, 50).Value = If(firstNameTextBox.TextLength = 0, CObj(DBNull.Value), firstNameTextBox.Text)
    .Add("@LastName", SqlDbType.VarChar, 50).Value = If(lastNameTextBox.TextLength = 0, CObj(DBNull.Value), lastNameTextBox.Text)
End With
 

Задав параметру значение NULL, вы фактически игнорируете его. Например, если @FirstName для параметра установлено значение NULL, то @FirstName IS NULL оно равно true, и этот первый набор критериев соответствует каждой строке, в противном случае он соответствует только тем строкам, которые содержат указанное имя. Аналогично для второго набора критериев. Вы можете сделать то же самое для любого количества наборов критериев, сколько захотите, сравнивая параметр с NULL или столбец с параметром.

Следует отметить, что в приведенном выше примере я использовал два параметра для четырех критериев. Это возможно, поскольку SqlClient поддерживает подлинные именованные параметры. С поставщиками, которые не поддерживают подлинные именованные параметры, например, Jet или ACE with OleDb , вам на самом деле нужно добавить в два раза больше параметров, потому что вы не можете использовать один и тот же параметр дважды в коде SQL, например

 Dim query = "SELECT * FROM Person WHERE (@FirstName1 IS NULL OR FirstName = @FirstName2) AND (@LastName1 IS NULL OR LastName = @LastName2)"
Dim command As New OleDbCommand

command.CommandText = query

Dim firstName = If(firstNameTextBox.TextLength = 0, CObj(DBNull.Value), firstNameTextBox.Text)
Dim lastName = If(lastNameTextBox.TextLength = 0, CObj(DBNull.Value), lastNameTextBox.Text)

With command.Parameters
    .Add("@FirstName1", SqlDbType.VarChar, 50).Value = firstName
    .Add("@FirstName2", SqlDbType.VarChar, 50).Value = firstName
    .Add("@LastName1", SqlDbType.VarChar, 50).Value = lastName
    .Add("@LastName2", SqlDbType.VarChar, 50).Value = lastName
End With
 

Комментарии:

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