Удаление окончательного «ИЛИ» из строки - PullRequest
3 голосов
/ 20 июня 2011

Я создаю SQL-запрос в VB.net и написал подпрограмму для динамического выполнения.

Я хочу включить каждый элемент в массив (неизвестного размера) в предложение where, как таковое:

Dim person(10) as String
Dim strSQL, strWhereClause as String
person(0) = "John"
person(1) = "Steve"
'...

For i = 0 To UBound(menuNames)
    strWhereClause &= "[name] = '" & person(i) & "' OR "
Next

strSQL= "SELECT * FROM [customers] WHERE " & strWhereClause 

Проблема в том, что в конце есть дополнительный " OR ". Есть аккуратный способ удалить это? Или, возможно, лучший способ подойти к проблеме все вместе. (Я думаю, string.join не будет работать в этой ситуации, потому что есть текст до и после элемента массива.)

РЕДАКТИРОВАТЬ: вручную удалить последние три символа, например, так: strWhereClause = Left(strWhereClause, strWhereClause.Length - 3) хорошо, за исключением того, что он не обрабатывает пустую строку. В конце концов, я не знаю, сколько элементов будет в моем массиве.

Ответы [ 9 ]

9 голосов
/ 20 июня 2011

Вы не должны делать это так, как вы, даже если вы на 100% уверены, какое содержимое хранится в массиве, это все еще плохая привычка. Вместо этого вы должны ознакомиться с параметризованными запросами .


Не проверено компиляцией:

var sb = new StringBuilder();
sb.Append("SELECT * FROM [customers] WHERE ");

for (int i = 0; i < person.Length; ++i)
{
    var param = string.Format("NAME{0}", i);
    sb.Append(string.Format("[NAME] = @{0}{1}", param, i < person.Length - 1 ? " OR " : string.Empty));
    command.Parameters.AddWithValue(param, person[i]);  
}

var sql = sb.ToString();

Предполагая, что вы SqlCommand command. Извините за C #, но мой VB слишком ржавый, я надеюсь, вы поняли. ;)

2 голосов
/ 20 июня 2011

Использование String.Join будет работать для этого, если вы также можете использовать LINQ.Я считаю, что приведенное ниже должно работать на dotNet 3.5 +

Dim person(2) As String
Dim out As String

person(0) = "Test 1"
person(1) = "Test 2"
person(2) = "Test 3"

out = String.Join(" Or ", person.Select(Function(n) String.Format("[name] = '{0}'", n)).ToArray)

Это приведет к следующему:

[name] = 'Test 1' Or [name] = 'Test 2' Or [name] = 'Test 3'

Просто добавьте 'out' к вашему SQL-выражению

2 голосов
/ 20 июня 2011

На мой взгляд, это зависит от вашей цели:
1. Наименьшие строки кода / код, который легче всего читать
2. Максимальная эффективность

На самом деле, Option2 имеет значение, только если строка становитсяочень долго или вы перестраиваете строку много-много раз.


Для краткого кода я бы выстроил строку, как вы делаете, а затем удалил биты, которые вы не делаетеneed ...

Dim person(10) as String
Dim strSQL, strWhereClause as String
person(0) = "John"
person(1) = "Steve"

i = -1
For i = 0 To UBound(menuNames)
    strWhereClause &= " OR [name] = '" & person(i) & "'"
Next
IF (i >= 0) THEN
  strWhereClause = RIGHT(strWhereClause, LEN(strWhereClause) - 3)
  strSQL= "SELECT * FROM [customers] WHERE " & strWhereClause 
END IF

Здесь есть две точки неэффективности ...
1. Конкатенация строк каждый раз, чтобы создать новую строку, требует много перераспределения памяти и копирования строки.
2. Обрезка последних трех символов подсчитывает всю длину строки, а затем копирует почти всю длину строки в новое выделенное место в памяти


ЕслиВы хотите немного большей эффективности, можно избежать неэффективности 2 сверху ...

Dim person(10) as String
Dim strSQL, strWhereClause as String
person(0) = "John"
person(1) = "Steve"

If (UBound(menuItems) >= 0) THEN
  strWhereClause &= " [name] = '" & person(0) & "'"

  If (UBound(menuItems) >= 1) THEN
    For i = 1 To UBound(menuNames)
        strWhereClause &= " OR [name] = '" & person(i) & "'"
    Next
  END IF

  strSQL= "SELECT * FROM [customers] WHERE" & strWhereClause 
END IF

(Это ставит проверку вне цикла, вы действительно не хотите проверять это каждое изменение).

1 голос
/ 27 июня 2011

Вот решение с использованием System.Text.StringBuilder:

Dim person(1) As String
Dim strSQL, strWhereClause As String
person(0) = "John"
person(1) = "Steve"
'...

Dim menuNames(person.Length - 1) As String
Dim Sb As New System.Text.StringBuilder
Dim i As Int32

Sb.Append("SELECT * FROM [customers] WHERE ")
For i = 0 To UBound(menuNames) - 1
    'strWhereClause &= "[name] = '" & person(i) & "' OR "
    Sb.Append("[name] = '")
    Sb.Append(person(i))
    Sb.Append("' OR ")
Next

Sb.Append("[name] = '")
Sb.Append(person(menuNames.Length - 1))
Sb.Append("'")

strSQL = Sb.ToString

ПРИМЕЧАНИЕ: Это решение протестировано с Visual Studio 2010.

1 голос
/ 20 июня 2011

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

Dim person(10) as String
Dim strSQL, strWhereClause as String
person(0) = "John"
person(1) = "Steve"
'...

For i = 0 To UBound(menuNames)
    If i = 0 Then
        strWhereClause &= "[name] = '" & person(i) & "'"
    Else
        strWhereClause &= " OR [name] = '" & person(i) & "'"
    EndIf
Next

strSQL= "SELECT * FROM [customers] WHERE " & strWhereClause 
0 голосов
/ 20 июня 2011

Не создавайте строку SQL до конца.Поместите каждое условие «ИЛИ» в Список , а затем выполните String.Join () с «ИЛИ».

0 голосов
/ 20 июня 2011

Вы можете использовать функцию Substring.

strWhereClause = strWhereClause.Substring(0, strWhereClause.Length - 3);

В приведенном выше примере используется C #.

0 голосов
/ 20 июня 2011

Конечно, вы можете просто удалить последние три символа strWhereClause перед назначением sqlStr?

Что-то вроде:

Next

strWhereClause = Mid(strWhereClause, 0, Len(strWhereClause) - 3)

strSQL= "SELECT * FROM [customers] WHERE " & strWhereClause 

Вам также нужно обработать исключение, когда есть 0 человек.

0 голосов
/ 20 июня 2011

добавить эту строку в конец:

strWhereClause = strWhereClause.replaceAll(" OR $", "");

упс - это Java. надеюсь, что вы можете использовать его:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...