#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 в соответствии с параметрами, указанными в оригинале, вы получаете один план для каждой ситуации, который почти наверняка будет лучше.