Подзапрос вернул более 1 значения - PullRequest
2 голосов
/ 09 ноября 2011

Я знаю, что эта тема повсюду, но я не делаю INSERT, UPDATE, DELETE. Мое утверждение является простым и простым SELECT утверждением, и до сих пор работало со 116 различными элементами в моей базе данных, пока я не дошел до одного.

У меня есть поисковая система, и я просматриваю каждый продукт в нашей базе данных, чтобы добавить к нему информацию. Все это делается через веб-сайт, но когда я ищу ProductID 331 и нажимаю на него, он переходит на страницу с сообщением об ошибке Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Для меня не имеет никакого смысла, что веб-сайт будет иметь ошибку только с этим одним продуктом. Это утверждение, которое я использую. Кто-нибудь знает, почему 1 продукт будет вызывать эту ошибку?

WebService:

Public Class ProductSearch
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetProducts(ByVal prefixText As String, ByVal count As Integer) 
                            As String()
    Dim ProductSql As String = "Select DISTINCT ProductID, ProductName 
                                FROM Product WHERE ProductName 
                                LIKE '%' & @prefixText & '%' 
                                ORDER BY ProductName ASC"
    Using sqlConn As New SqlConnection
     (System.Configuration.ConfigurationManager.ConnectionStrings
     ("LocalSqlServer").ConnectionString)
        sqlConn.Open()
        Dim myCommand As New SqlCommand(ProductSql, sqlConn)
        myCommand.Parameters.Add("@prefixText", SqlDbType.VarChar, 50)
                                 .Value = prefixText
        Dim myReader As SqlDataReader = myCommand.ExecuteReader()
        Dim myTable As New DataTable
        myTable.TableName = "ProductSearch"
        myTable.Load(myReader)
        sqlConn.Close()
        Dim items As String() = New String(myTable.Rows.Count - 1) {}
        Dim i As Integer = 0
        For Each dr As DataRow In myTable.Rows
            Dim id As String = dr("ProductID").ToString()
            Dim name As String = dr("ProductName").ToString()
            Dim item As String = AjaxControlToolkit.AutoCompleteExtender
                                .CreateAutoCompleteItem(name, id)
            items.SetValue(item, i)
            i += 1
        Next
        Return items
    End Using
End Function
End Class

Страница aspx, которая вызывает веб-сервис:

<%@ Page Title="Product Search" Language="VB" MasterPageFile="~/MasterPage.master"
 AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="Default" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" 
 TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
<script type="text/javascript">
function AutoCompleteClientMethod(source, eventArgs) {
    var value = eventArgs.get_value();
    window.location = ("/Product/Default.aspx?id=" + value)
} 
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server">


    <asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="ProductSearch.asmx" />
    </Services>
</asp:ScriptManager>    


    <asp:TextBox ID="Search" runat="server" AutoComplete="off"></asp:TextBox>
    <asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
      TargetControlID="Search" ServicePath="~/ProductSearch.asmx" 
      ServiceMethod="GetProducts" MinimumPrefixLength="1" CompletionSetCount="120" 
      EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod">
    </asp:AutoCompleteExtender>
  </div><!--End of main div -->
</asp:Content>

ОБНОВЛЕНИЕ: 9/9/2011 - Я нашел еще пару записей с этой проблемой. Это ProductID 331-335. Я понятия не имею, что здесь происходит. Может ли быть так, что этих продуктов на самом деле не существует или в них есть какая-то ошибка?

Вот список ProductID и соответствующих им ProductNames, которые имеют эту ошибку:

122 'Managed account section of the Web Site'
331 'Elliott Wave Principle Key to Market Behavior'
332 'Targeting Profitable Entry & Exit Points'
333 'Essentials of Trading It's not WHAT You Think, It's HOW You Think'
334 'Exceptional Trading The Mind Game'
335 'Fibonacci Analysis'

Ответы [ 3 ]

3 голосов
/ 09 ноября 2011

Помимо ответа Рика, я бы добавил, что вам никогда не следует объединять строки для формирования операторов SQL.Вместо этого используйте параметризованные запросы.Конкатенация строк подвергает вас атакам SQL-инъекций.Кроме того, используя параметризованные запросы, вы можете повысить производительность, если планы запросов можно использовать повторно.

См. Этот другой пост StackOverflow для хорошего обсуждения параметризованных запросов в VB.NET.

3 голосов
/ 09 ноября 2011

Я полагаю, что это запрос дополнительного выбора, DISTINCT не означает один результат. Вы можете использовать TOP 1, чтобы гарантировать один результат, но это не гарантирует, что вы хотите.

Select TOP 1 DISTINCT ProductID, ProductName 
FROM Product WHERE ProductName 
LIKE '%" & prefixText & "%' 
ORDER BY ProductName ASC
0 голосов
/ 10 ноября 2011

Я понял, в чем проблема. По некоторым причинам этим проблемным продуктам присваивается более одного значения в полях данных, которые ДОЛЖНЫ иметь только один элемент. База данных была недавно изменена, чтобы этого не произошло, но я думаю, что эти 5 продуктов уже испорчены и теперь обнаружены.

Спасибо за помощь, ребята! Я хотел бы подумать, чтобы проверить в базу данных раньше. (Там около 15 таблиц, так что обычно это то, что я думаю сделать последним)

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