子查询返回超过 1 个值
我知道这个话题无处不在,但我并没有执行INSERT
、UPDATE
、DELETE
。我的语句是一个简单明了的 SELECT
语句,到目前为止,我已经处理了数据库中的 116 个不同项目,直到找到一个。
我有一个搜索引擎,正在浏览我们数据库中的每一个产品以向其中添加信息。这一切都是通过网站完成的,但是当我搜索 ProductID 331 并单击它时,它会转到错误页面,显示 Subquery returned more than 1 value。当子查询跟随 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。
这对我来说没有任何意义该网站仅会因这一种产品而出错。 这是我正在使用的声明。有谁知道为什么 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
调用 Web 服务的 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>
更新:2011 年 11 月 9 日 - 我发现了更多存在此问题的记录。它们是 ProductID 331-335。我不知道这里发生了什么事。这些产品是否真的存在或者存在某种错误?
以下是出现此错误的 ProductID 及其相应的 ProductName 的列表:
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'
I know this topic is all over the place, but I am not doing an INSERT
, UPDATE
, DELETE
. My statement is a plain and simple SELECT
statement and so far has worked with 116 different items in my database until I got to one.
I have a search engine and am going through every single product in our database to add information to it. This is all done through the website, but when I search for ProductID 331 and click on it, it goes to the error page that says Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
It doesn't make any sense to me that the website would error with only this one product.
This is the statement I am using. Does anyone know why 1 product would be causing this error?
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
The aspx page that calls the webservice:
<%@ 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>
UPDATE: 11/9/2011 - I have found a couple more records that have this problem. They are ProductID 331-335. I have no idea what is going on here. Could it be that those products don't really exist or that they have some kind of bug?
Here is a list of ProductIDs and their corresponding ProductNames that have this error:
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'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我假设这是子选择查询,DISTINCT 并不意味着一个结果。您可以使用 TOP 1 来保证一个结果,但它不能保证它是您想要的结果。
I assume this is the sub-select query, DISTINCT doesn't mean one result. You can use TOP 1 to guarantee one result, but it doesn't guarantee it is the one you want.
除了 Rick 的回答之外,我还想补充一点,永远不应该连接字符串来形成 SQL 语句。请改用参数化查询。字符串连接会使您遭受 SQL 注入攻击。此外,通过使用参数化查询,如果查询计划可以重用,您可能会获得性能提升。
请参阅另一篇 StackOverflow 帖子,了解关于VB.NET 上的参数化查询。
Besides Rick's answer, I would add that you should never concatenate strings to form SQL statements. Use parametrized queries instead. String concatenation exposes you to SQL Injection attacks. Also, by using parametrized queries you may gain performance if the query plans can be reused.
See this other StackOverflow post for a good discussion regarding parametrized queries on VB.NET.
我知道问题出在哪里了。由于某种原因,这些有问题的产品在数据字段中分配了多个值,而这些值应该只有一项。最近数据库已经更改,所以不会发生这种情况,但我猜这 5 个产品已经搞乱了,现在已经被发现了。
感谢大家的帮助!我希望我能早点考虑进一步检查数据库。 (大概有15张桌子,所以我通常会想到最后做)
I figured out what the problem is. For some reason, these problematic products have more than one value assigned to them in data fields that SHOULD have only one item. The database has been changed recently so that doesn't happen, but I guess these 5 products were already messed up and have now been found out.
Thanks for all the help guys! I wish I would've thought to check further into the database sooner. (There are about 15 tables, so it's usually what I think of to do last)