Запрос OLEDB на SQL Server не работает

У меня есть два SQL-запроса:

а.

SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
     upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
FROM atable ;

и

В.

SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
      upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
 FROM atable  WHERE userCompareStr='GAPYLE1111' ;

У меня есть следующий код:

    Dim sql As String
    Dim conn As OleDbConnection
    Dim cmd As OleDbDataAdapter
    Dim ds As DataSet
    Dim tbl As DataTable

    conn = " something here "
    cmd = New OleDbDataAdapter(sql, conn)
    ds = New DataSet
    cmd.Fill(ds)
    tbl = New DataTable
    tbl = ds.Tables(0)

Рядом, поскольку я могу сказать, что это работает, когда sql установлен в строку A, но не тогда, когда он устанавливает строку B.

Это заставляет меня подозревать, что в предложении есть что-то не так  WHERE userCompareStr = 'GAPYLE1111'

Могу ли я использовать псевдоним userCompareStr таким образом? Я не могу найти примеров такого использования, но я нахожу аналогичное использование, когда псевдоним используется для имени таблицы - и я ничего не вижу против такого типа.

Ответ 1

У вас есть три варианта.

1) повторите то, что вы сделали в выборе в

SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
      upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
FROM atable  

WHERE  (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
      upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) ='GAPYLE1111' ;

2) Используйте общее выражение таблицы

with CTE AS 
(SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
      upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
FROM atable  )
SELECT userCompareStr FROM CTE where userCompareStr = 'GAPYLE1111';

3) Встроенный запрос см. ответ Мазиар Тахери

В стороне я надеюсь, что "GAPYLE1111" не исходит от ввода пользователя, иначе вы подвергаете себя атакам SQL Injection. Вместо этого используйте параметризованные запросы

Ответ 3

вы не можете использовать псевдоним, который вы установили в предложении select, внутри предложения where.

попробуйте следующее:

SELECT * FROM
(
SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr FROM atable)
as nested
WHERE userCompareStr='GAPYLE1111' ;

Ответ 4

Я некоторое время отошел от проблемы, работал над чем-то еще и вернулся к ней. Я решил основную проблему, переключившись с использования oledb на "что-то еще". Я не уверен, что новый метод (для меня) вызывается - кроме, может быть, "native sqlserver?"

Важные моменты:

  • Нельзя использовать псевдоним имени поля в предложении WHERE. (согласно мазиар и матовый)

  • Conrad fix # 1 работал над OLEDB, но мне не нравится этот метод, потому что он подробный (и реальная команда намного сложнее, чем уменьшенный пример, который я предоставляю здесь), и есть много разные вызовы. Непростой и трудно читаемый (но работает в крайнем случае).

  • Чтобы получить либо СН, либо вложенную операцию выбора, мне пришлось переключиться с OLEDB на "native sqlserver" (или как он там называется). СО (как было предложено Конрадом) является моим предпочтительным решением - гораздо легче читать. Вложенный выбор (предложенный Maziar) также работает, когда я переключаюсь с OLEDB на native.

  • Мне нужно переключиться на "параметризованные запросы", чтобы избежать атак sql-инъекций, как отметил Конрад.

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

Provider=SQLOLEDB

Я использовал:

providerName="System.Data.SqlClient"

Теперь я не ссылаюсь на oledb (например, oledbadapter), но вместо этого делаю ссылки на sqlDataAdapter. Я игнорирую функции upper, ltrim и trim (потому что получается, что это не проблема) и сосредоточиться на WITH, который был удушающим. Вот что я должен работать:

    Dim conn As New SqlConnection("server=localhost;database=DB;Integrated Security=SSPI;")
    Dim sql As String
    Dim da As SqlDataAdapter

    Dim ds As DataSet = New DataSet()
    Dim tbl As DataTable = New DataTable

    conn = New SqlConnection()
    conn.ConnectionString =    ConfigurationManager.ConnectionStrings("DB").ConnectionString

    Sql = " WITH cte AS "
    sql = sql & "(lastname + firstname + middlename"
    Sql = Sql & "     + v) as userCompareStr FROM atable ) "
    sql = sql & "SELECT userCompareStr   FROM cte WHERE userCompareStr = '" & "GAPYLE1111" & "' ;"

    da = New SqlDataAdapter(sql, conn)
    da.Fill(ds)
    tbl = ds.Tables(0)
    TextBox2.Text = sql

    If tbl.Rows.Count < 1 Then
        TextBox1.Text = "no items"
    Else
        TextBox1.Text = tbl.Rows.Count & " items selected"
    End If


    conn.Dispose()

Кроме того, в web.config я добавил:   

Я еще не добавил файл исправления SQL Injection, но я изучаю его, и теперь я уверен, что это то, что мне нужно сделать. Я нашел информацию об этом здесь:

http://msdn.microsoft.com/en-us/library/ff648339.aspx

и здесь:

http://weblogs.asp.net/cibrax/archive/2006/09/28/Parameterized-Queries-_2800_Oracle_2C00_-SQLServer_2C00_-OleDb_2900_.aspx

но мне нужно некоторое время, чтобы поэкспериментировать с ним. Спасибо за помощь и указатели.