Запрос 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. Вместо этого используйте параметризованные запросы
Ответ 2
Нет, вы не можете использовать столбец с псевдонимом в предложении WHERE.
См. Использование столбца Alias в предложении where в ms-sql 2000
(статья о SQL 2000, но она по-прежнему применяется сегодня)
Ответ 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
но мне нужно некоторое время, чтобы поэкспериментировать с ним. Спасибо за помощь и указатели.