SQL Server子查询返回超过1个值。当子查询遵循=, !=, , >=时,这是不允许的。

94 人关注

我运行以下查询。

SELECT 
   orderdetails.sku,
   orderdetails.mf_item_number,
   orderdetails.qty,
   orderdetails.price,
   supplier.supplierid,
   supplier.suppliername,
   supplier.dropshipfees,
   cost = (SELECT supplier_item.price
           FROM   supplier_item,
                  orderdetails,
                  supplier
           WHERE  supplier_item.sku = orderdetails.sku
                  AND supplier_item.supplierid = supplier.supplierid)
FROM   orderdetails,
       supplier,
       group_master
WHERE  invoiceid = '339740'
AND orderdetails.mfr_id = supplier.supplierid
       AND group_master.sku = orderdetails.sku  

我得到以下错误。

Msg 512, Level 16, State 1, Line 2 子查询返回1个以上的值。当子查询跟随=, !=, <, <= , >, >=或者子查询作为表达式使用时,这是不允许的。

有什么想法吗?

4 个评论
哦,停止使用隐含的连接语法,这是一个非常糟糕的做法,更难维护,更容易出错。
@HLGEM 为什么它的做法不好,更难维护,更容易犯错?
这些表是根据什么字段连接的?提示:我说不出来的事实就是问题所在。
Paul
@reggaeguitar - 我个人认为隐含连接更难理解。实际上,我不得不停下来注意 WHERE 子句,以确保连接的正确实现。 如果隐含条件分散在整个子句中,就会变得更加困难,并且降低了可读性。就像所有的编程语言一样,语义的使用是使你的SQL更易读的关键--所有的连接都应该被正确地定义为 FROM 子句的一个小节--这样,你就知道你的数据来自哪里,更重要的是, 为什么
sql
sql-server
tsql
Anilkumar
Anilkumar
发布于 2010-04-16
11 个回答
Jeffrey L Whitledge
Jeffrey L Whitledge
发布于 2019-11-11
已采纳
0 人赞同

试试这个。

SELECT
    od.Sku,
    od.mf_item_number,
    od.Qty,
    od.Price,
    s.SupplierId,
    s.SupplierName,
    s.DropShipFees,
    si.Price as cost
    OrderDetails od
    INNER JOIN Supplier s on s.SupplierId = od.Mfr_ID
    INNER JOIN Group_Master gm on gm.Sku = od.Sku
    INNER JOIN Supplier_Item si on si.SKU = od.Sku and si.SupplierId = s.SupplierID
WHERE
    od.invoiceid = '339740'

这将返回多条除cost列外相同的行。看一下返回的不同成本值,并找出导致不同成本值的原因。然后问别人他们想要哪个成本值,并在查询中添加选择该成本的标准。

jk.
jk.
发布于 2019-11-11
0 人赞同

检查一下你试图执行查询的表上是否有任何触发器。它们有时会抛出这个错误,因为它们正试图运行表上的更新/选择/插入触发器。

你可以修改你的查询,以禁用然后启用触发器,如果触发器 不需要 为你试图运行的任何查询执行。

ALTER TABLE your_table DISABLE TRIGGER [the_trigger_name]
UPDATE    your_table
SET     Gender = 'Female'
WHERE     (Gender = 'Male')
ALTER TABLE your_table ENABLE TRIGGER [the_trigger_name]
TT.
修复触发器不是比禁用它们更好吗?这些触发器的创建是有原因的,不是吗?你可能会因为禁用触发器而绕过一些重要的功能......
jk.
@TT.是的,但请看答案中加粗的文字。你可以修改你的查询,如果触发器不需要为你试图运行的任何查询执行,就可以禁用然后启用触发器。
在查询过程中改变表是绝对可怕的。 如果你需要跳过触发器,请在每个连接的基础上进行。
Diyar sereroy
Diyar sereroy
发布于 2019-11-11
0 人赞同
SELECT COLUMN
FROM TABLE
WHERE columns_name
    IN ( SELECT COLUMN FROM TABLE WHERE columns_name = 'value');

注意:当我们使用子查询时,必须关注这些要点。

  • 如果我们的子查询返回1个值,在这种情况下我们需要使用(=,!=,<>,<,>....)
  • else(不止一个值),在这种情况下,我们需要使用(in, any, all, some )。
  • Mayo
    Mayo
    发布于 2019-11-11
    0 人赞同
    cost = Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier 
       where Supplier_Item.SKU=OrderDetails.Sku and 
          Supplier_Item.SupplierId=Supplier.SupplierID
    

    这个子查询返回多个值,SQL正在抱怨,因为它不能在一条记录中给cost分配多个值。

    一些想法。

  • 修复数据,使现有的子查询只返回1条记录
  • 修复子查询,使其只返回一条记录
  • 在子查询中添加top 1和order by(DBA讨厌的解决方案 - 但它 "有效")。
  • 使用一个用户定义的函数将子查询的结果串联成一个字符串
  • 关于3;所有 有能力的 开发人员也应该讨厌这样。前一阵子有一个关于 "Pet Peeves "的问题;而我的问题是。"没有错误信息,并不意味着它'有效'!"。也就是说,你可以添加#5:重组整个查询;也就是说,不是获取客户和 "查找 "发票;而是获取发票和 "查找 "客户。
    HLGEM
    HLGEM
    发布于 2019-11-11
    0 人赞同

    解决的办法是停止使用相关子查询,而使用连接来代替。相关子查询本质上是游标,因为它们导致查询逐行运行,应避免使用。

    如果你只想让一条记录匹配,你可能需要在连接中使用一个派生表,以便在字段中获得你想要的值,如果你需要两个值,那么普通的 join 会做到这一点,但是你会在结果集中得到同一id的多条记录。如果你只想要一个,你需要决定哪一个,并在代码中做到这一点,你可以使用带有 order by top 1 ,你可以使用 max() ,你可以使用 min() ,等等,这取决于你对数据的真正要求是什么。

    JAN
    JAN
    发布于 2019-11-11
    0 人赞同

    我有同样的问题,我用 in 代替了 = ,来自 Northwind 数据库的例子。

    查询内容是:找到1997年下订单的公司

    试试这个:

    SELECT CompanyName
        FROM Customers
    WHERE CustomerID IN (
                            SELECT CustomerID 
                                FROM Orders 
                            WHERE YEAR(OrderDate) = '1997'
    

    而不是那个:

    SELECT CompanyName
        FROM Customers
    WHERE CustomerID =
        SELECT CustomerID 
            FROM Orders 
        WHERE YEAR(OrderDate) = '1997'
    
    egrunin
    egrunin
    发布于 2019-11-11
    0 人赞同

    要么你的数据是坏的,要么它的结构不是你认为的那样。 可能两者都有。

    为了证明/反驳这一假设,运行这个查询。

    SELECT * from
        SELECT count(*) as c, Supplier_Item.SKU
        FROM Supplier_Item
        INNER JOIN orderdetails
            ON Supplier_Item.sku = orderdetails.sku
        INNER JOIN Supplier
            ON Supplier_item.supplierID = Supplier.SupplierID
        GROUP BY Supplier_Item.SKU
    WHERE c > 1
    ORDER BY c DESC
    

    如果这只返回几行,那么你的数据就很糟糕。如果它返回很多行,那么你的数据的结构就不是你认为的那样。(如果它返回零行,那就是我错了

    我猜测你的订单多次包含同一SKU(两个独立的行项目,都订购同一SKU)。

    cjk
    cjk
    发布于 2019-11-11
    0 人赞同

    你的选择语句中的成本部分正在返回一个以上的值。 你需要添加更多的where子句,或者使用一个聚合语句。

    Dave Costa
    Dave Costa
    发布于 2019-11-11
    0 人赞同

    这个错误意味着这个子查询要返回超过1条记录。

    (Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )
    

    你可能不想在子查询中包括orderdetails和supplier表,因为你想在外层查询中引用从这些表中选择的值。 因此,我认为你希望子查询是简单的。

    (Select Supplier_Item.Price from Supplier_Item where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )
    

    我建议你阅读一下相关与非相关的子查询。

    KP Taylor
    KP Taylor
    发布于 2019-11-11
    0 人赞同

    正如其他人所建议的,最好的方法是使用连接而不是变量赋值。 重写你的查询以使用连接(并使用显式连接语法而不是隐式连接,这也是建议的--而且是最好的做法),你会得到这样的结果。

    select  
      OrderDetails.Sku,
      OrderDetails.mf_item_number,
      OrderDetails.Qty,
      OrderDetails.Price,
      Supplier.SupplierId, 
      Supplier.SupplierName,
      Supplier.DropShipFees, 
      Supplier_Item.Price as cost
      OrderDetails
    join Supplier on OrderDetails.Mfr_ID = Supplier.SupplierId
    join Group_Master on Group_Master.Sku = OrderDetails.Sku 
    join Supplier_Item on 
      Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID 
    where 
      invoiceid='339740'
    
    Shammie
    Shammie
    发布于 2019-11-11
    0 人赞同

    即使在原帖的9年后,这对我也有帮助。

    如果你在没有任何线索的情况下收到这些类型的错误,应该有一个与表相关的触发器、函数,显然它应该以SP结束,或以选择/过滤数据 不使用 主唯一列的函数结束。如果你使用Primary Unique列进行搜索/过滤,就不会有任何多重结果。特别是当你为一个声明的变量赋值时。SP从来不会给你错误,而只是一个运行时错误。

     "System.Data.SqlClient.SqlException (0x80131904): Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
        The statement has been terminated."
    

    在我的案例中,显然没有任何线索,只有这个错误信息。有一个触发器连接到表,被触发器更新的表也有另一个触发器,同样,它最终有两个触发器,最后有一个SP。该SP有一个选择子句,导致了多条记录。

    SET @Variable1 =(