SQLServerサブクエリが複数の値を返しました。サブクエリが=、!=、<、<=、>、> =の後に続く場合、これは許可されません。


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

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 2018

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. 1つのレコードのみを返すようにサブクエリを修正します
  3. トップ1を追加し、サブクエリに並べ替えます(DBAが嫌う厄介なソリューションですが、「機能」します)
  4. ユーザー定義関数を使用して、サブクエリの結果を単一の文字列に連結します

5
3日; すべての有能な開発者もそれを嫌うべきです。しばらく前に「PetPeeves」について質問がありました。「エラーメッセージがないからといって、それが「機能する」という意味ではありません!」そうは言っても、#5を追加できます。クエリ全体を再構築します。つまり、顧客と「ルックアップ」の請求書を取得する代わりに。むしろ請求書と「ルックアップ」顧客を取得します。
幻滅2010

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

これがほんの数行を返す場合、データは不良です。大量の行が返される場合、データは思ったとおりに構造化されていません。(ゼロ行が返される場合、私は間違っています。

同じものをSKU複数回含む注文があると思います(2つの別々の広告申込情報、両方とも同じ注文SKU)。


10

修正は、相関サブクエリの使用を停止し、代わりに結合を使用することです。相関サブクエリは、クエリを行ごとに実行するため、本質的にカーソルであり、回避する必要があります。

1つのレコードのみを一致させたい場合、フィールドで必要な値を取得するために、結合に派生テーブルが必要になる場合があります。両方の値が必要な場合は、通常の joinはを行いますが、同じIDに対して複数のレコードを取得します。結果セットで。あなたは一つだけをしたい場合、あなたはどちらを決定する必要があり、コードでは、あなたが使用できることを行うtop 1order 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

selectのcost部分のselectステートメントが複数の値を返しています。where句をさらに追加するか、集計を使用する必要があります。


4

このエラーは、このサブクエリが複数の行を返していることを意味します。

(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 )

相関サブクエリと非相関サブクエリを確認することをお勧めします。


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."

私の場合、明らかに手がかりはありませんでしたが、このエラーメッセージだけでした。テーブルに接続されたトリガーがあり、トリガーによって更新されたテーブルにも別のトリガーがあり、同様に2つのトリガーで終了し、最終的に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.