2011-11-08 124 views
2

我知道这个题目是所有的地方,但我没有做一个INSERTUPDATEDELETE。我的陈述是一个简单而简单的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页面调用web服务:

<%@ 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> 

更新:11/9/2011 - 我已经发现一对夫妇更多的记录有这个问题。他们是产品ID 331-335。我不知道这里发生了什么。难道这些产品不是真的存在,或者它们有某种错误?

这里是ProductIDs,并且有这样的错误及其对应的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

中有没有子查询,你一定是你的代码中完整的查询?次要的问题:PrefixText将是更好的也可以是绑定变量,而不是字符串连接,以避免潜在的SQL注入 – Andrew

+0

@Andrew我更新了我的代码 – jlg

+0

我没有这使我想知道为什么这个错误是发生任何的子查询。我能想到的唯一的事情是,当javascript函数尝试重定向用户时,它的功能会拉回多个值。 – jlg

回答

0

我想通了什么问题。出于某种原因,这些有问题的产品在应该只有一个项目的数据字段中为它们分配了多个值。数据库最近已经改变,所以不会发生,但我想这5个产品已经搞砸了,现在已经被发现了。

感谢所有的帮助家伙!我希望我能早点考虑进一步检查数据库。 (大约有15桌,所以它通常是什么,我想做到最后)

3

我想这是子选择查询,DISTINCT并不意味着一个结果。您可以使用TOP 1来保证一个结果,但不能保证它是您想要的结果。

Select TOP 1 DISTINCT ProductID, ProductName 
FROM Product WHERE ProductName 
LIKE '%" & prefixText & "%' 
ORDER BY ProductName ASC 
+0

我试过,但现在我的搜索引擎不起作用。 :(没有结果显示 – jlg

3

除了瑞克的答案,我会补充说,你不应该连接字符串来形成SQL语句。改用参数化查询。字符串串联暴露给你SQL注入攻击。另外,通过使用参数化查询,如果可以重用查询计划,您可能会获得性能。

See this other StackOverflow post for a good discussion regarding parametrized queries on VB.NET.

+0

我不确定如何参数化前缀文本,但用户在我的另一个帖子上回来的时候实际上已经有了整个时间的答案。我更新了它:) – jlg

+0

@jlg当你看到它遵循这种危险模式时,不要害怕改变别人的代码。最初编写代码的人/ gal可能不再与该公司在一起,现在你负责了。它也会让你的生活更轻松!无论如何,我很高兴你整理出来;) – Icarus

+0

是的,你说得对。即使它是一团糟,改变现有方式的东西也是有点神经过于紧张。我只有5个月的“现实世界”。我在大学时没有足够的学习,所以希望我不会太落后! – jlg