SQL Server 하위 쿼리가 둘 이상의 값을 반환했습니다. 하위 쿼리가 =,! =, <, <=,>,> = 뒤에 오는 경우에는 허용되지 않습니다.


84

다음 쿼리를 실행합니다.

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  

다음과 같은 오류가 발생합니다.

메시지 512, 수준 16, 상태 1, 줄 2 하위 쿼리가 둘 이상의 값을 반환했습니다. 하위 쿼리가 =,! =, <, <=,>,> = 뒤에 오는 경우 또는 하위 쿼리가 표현식으로 사용되는 경우에는 허용되지 않습니다.

어떤 아이디어?


40
오, 묵시적 조인 구문 사용을 중단하십시오. 매우 열악하고 유지 관리가 어렵고 실수하기 쉽습니다.
HLGEM 2010

1
@HLGEM 왜 연습이 좋지 않고 유지 관리가 더 어렵고 실수하기가 더 쉬운가요?
reggaeguitar 2019

5
이 테이블은 어떤 필드에 조인됩니까? 힌트 : 내가 말할 수 없다는 사실이 문제입니다.
naughtilus

답변:


49

이 시도:

SELECT
    od.Sku,
    od.mf_item_number,
    od.Qty,
    od.Price,
    s.SupplierId,
    s.SupplierName,
    s.DropShipFees,
    si.Price as cost
FROM
    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. 반환되는 다른 비용 값을보고 다른 값의 원인을 파악합니다. 그런 다음 누군가에게 원하는 비용 값을 물어보고 해당 비용을 선택할 쿼리에 기준을 추가하십시오.


44

쿼리를 실행하려는 테이블에 트리거가 있는지 확인하십시오. 테이블에있는 업데이트 / 선택 / 삽입 트리거를 실행하려고 할 때 때때로이 오류가 발생할 수 있습니다.

당신은 트리거가있는 경우 다음 트리거를 사용하지 않도록 설정하는 쿼리를 수정할 수 있습니다 하지 않습니다 당신이 실행하려는 어떤 쿼리를 실행해야합니다.

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]

4
트리거를 비활성화하는 것보다 수정하는 것이 더 낫지 않습니까? 그 방아쇠는 이유 때문에 만들어졌습니다. 트리거를 비활성화하여 몇 가지 중요한 기능을 우회 할 수 있습니다 ...
TT.

3
@TT. 예,하지만 답변에서 굵게 표시된 텍스트를 참조하십시오. 실행하려는 쿼리에 대해 트리거를 실행할 필요가없는 경우 쿼리를 수정하여 비활성화 한 다음 트리거를 활성화 할 수 있습니다.
jk.

1
쿼리 중에 테이블을 변경하는 것은 절대적으로 끔찍합니다. 트리거를 건너 뛰어야하는 경우 연결별로 수행하십시오.
Ben Voigt

26
SELECT COLUMN 
    FROM TABLE 
WHERE columns_name
    IN ( SELECT COLUMN FROM TABLE WHERE columns_name = 'value');

참고 : 하위 쿼리를 사용할 때 다음 사항에 중점을 두어야합니다.

  1. 이 경우 하위 쿼리가 1 값을 반환하면 (=,! =, <>, <,> ....)
  2. else (하나 이상의 값),이 경우 (in, any, all, some)

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

이 하위 쿼리는 여러 값을 반환합니다. SQL은 단일 레코드의 비용에 여러 값을 할당 할 수 없기 때문에 불평합니다.

몇 가지 아이디어 :

  1. 기존 하위 쿼리가 1 개의 레코드 만 반환하도록 데이터를 수정합니다.
  2. 하나의 레코드 만 반환하도록 하위 쿼리를 수정합니다.
  3. 하위 쿼리에 상위 1 개를 추가하고 순서를 지정합니다 (DBA가 싫어하는 불쾌한 솔루션-하지만 "작동").
  4. 사용자 정의 함수를 사용하여 하위 쿼리의 결과를 단일 문자열로 연결

5
3에; 모든 유능한 개발자는 또한 그것을 싫어해야합니다. 얼마 전에 'Pet Peeves'에 대한 질문이있었습니다. 그리고 내 것입니다 : "오류 메시지가 없다고해서 '작동'한다는 의미는 아닙니다!". 즉, # 5를 추가 할 수 있습니다. 전체 쿼리를 재구성합니다. 즉, 고객 및 '조회'송장을받는 대신; 오히려 인보이스를 받고 고객을 '조회'합니다.
환멸

10

데이터가 나쁘거나 생각하는 방식으로 구조화되지 않았습니다. 둘 다 가능합니다.

이 가설을 증명 / 반증하려면 다음 쿼리를 실행하십시오.

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
) x
WHERE c > 1
ORDER BY c DESC

이것이 몇 개의 행만 반환하면 데이터가 잘못된 것 입니다. 많은 행을 반환하면 데이터가 생각한 방식으로 구조화되지 않은 것입니다. (0 행을 반환하면 잘못된 것입니다. )

동일한 SKU항목을 여러 번 포함하는 광고 주문이 있다고 생각합니다 (두 개의 개별 광고 항목, 둘 다 같은 항목을 주문 함 SKU).


10

수정 사항은 상관 하위 쿼리 사용을 중지하고 대신 조인을 사용하는 것입니다. 상관 된 하위 쿼리는 쿼리가 행 단위로 실행되도록하고 피해야하므로 본질적으로 커서입니다.

하나의 레코드 만 일치 시키려면 필드에서 원하는 값을 얻기 위해 조인에 파생 테이블이 필요할 수 있습니다. 두 값이 모두 필요한 경우 일반 사용자 join가 수행하지만 동일한 ID에 대해 여러 레코드를 얻습니다. 결과 세트에서. 당신이 하나를 원하는 경우에, 당신은 어느 하나를 결정해야하고 코드에서, 당신이 사용할 수 그렇게 top 1와 함께 order by, 당신은 사용할 수 있습니다 max()당신은 사용할 수, min()데이터에 대한 실제 요구 사항이 무엇인지에 따라, 등.


9

나는 데이터베이스 예제 에서 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'
);

6

선택 비용 부분의 선택 문이 둘 이상의 값을 반환합니다. where 절을 더 추가하거나 집계를 사용해야합니다.


4

이 오류는이 하위 쿼리가 2 개 이상의 행을 반환 함을 의미합니다.

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

외부 쿼리의 해당 테이블에서 선택한 값을 참조하기 때문에 하위 쿼리에 orderdetails 및 공급자 테이블을 포함하지 않을 수 있습니다. 따라서 하위 쿼리가 간단하기를 원한다고 생각합니다.

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

상관 관계가없는 하위 쿼리와 관련이없는 하위 쿼리를 읽어 보는 것이 좋습니다.


3

다른 사람들이 제안했듯이이를 수행하는 가장 좋은 방법은 변수 할당 대신 조인을 사용하는 것입니다. 조인을 사용하도록 쿼리를 다시 작성하면 (또한 제안 된 암시 적 조인 대신 명시 적 조인 구문을 사용하는 것이 좋습니다) 다음과 같은 결과를 얻을 수 있습니다.

select  
  OrderDetails.Sku,
  OrderDetails.mf_item_number,
  OrderDetails.Qty,
  OrderDetails.Price,
  Supplier.SupplierId, 
  Supplier.SupplierName,
  Supplier.DropShipFees, 
  Supplier_Item.Price as cost
from 
  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' 

1

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에 여러 행을 생성하는 select 절이 있습니다.

SET @Variable1 =(
        SELECT column_gonna_asign
        FROM dbo.your_db
        WHERE Non_primary_non_unique_key= @Variable2

여러 행을 반환하면 문제가있는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.