0

クエリを実行すると、エラー [ORA-01427: 単一行のサブクエリが複数の行を返します] が表示されます。次のような構造のクエリがあります。

SELECT LV.PRICE,
 (SELECT C.MODEL_NAME FROM CARS C WHERE C.MODEL_ID = LV.MODEL_ID) as MODEL_NAME
FROM LEDGER_VIEW LV
WHERE LV.PRICE < 500

ネストされた選択で壊れています。ビューとこのクエリの両方のロジックが正しく、ネストされた選択が複数の行を返す可能性がないことはわかっています。CARS テーブルの MODEL_ID は一意のフィールドです。ネストされた選択なしでクエリを実行すると、このエラーは返されません。

LEDGER_VIEW は、別のビューの上に構築されたビューです。Oracle 10g でこれらのスタック ビューにバグがある可能性はありますか? この問題をデバッグする他の方法がわかりません。

この特定のクエリをネストされた選択ではなく結合に変更できることは承知していますが、簡単に変更できない他の場所でネストされたクエリを使用しているため、なぜこれが起こっているのか知りたいです。

編集:これは本当に奇妙なことです。LEDGER_VIEW は、私が言ったように、別のビューの上に構築されています。テストとして、ネストされたビューの SQL を、ネストされたビューの代わりに LEDGER_VIEW の SQL の SQL に直接コピーしたところ、(予想どおり) エラーなしで返されました。これは、ネストされたビューまたはネストされたビューとデータベースリンクの組み合わせのいずれかでバグのある動作があることを確認しているようです。

4

5 に答える 5

4

サブクエリが複数の行を返しています。次のクエリを使用して、テーブル内で重複MODELIDしている値を見つけます。Car

select MODELID as CarsModelID, count(*) as Count
from cars 
where MODELID in (
    select MODEL_ID
    from LEDGER_VIEW  
    WHERE LV.PRICE < 500 
)
group by MODELID
having count(*) > 1
于 2010-09-27T14:36:42.433 に答える
2

スタック ビューを作成しても再作成できません。(RedFiltersは犯人を見つけますが)

    CREATE TABLE t1
    (
        t1_id NUMBER        ,
        txt   VARCHAR2( 50 ),
        CONSTRAINT t1_pk PRIMARY KEY( t1_id )
    ) ;


    CREATE TABLE t2
    (
        t2_id NUMBER                      ,
        t1_id NUMBER                      ,
        price NUMBER( 10, 4 )             ,
        CONSTRAINT t2_pk PRIMARY KEY( t2_id ),
        CONSTRAINT t2_fk FOREIGN KEY( t1_id ) REFERENCES t1( t1_id )
    );

    insert into t1(t1_id, txt) values(1,'fit');
    insert into t1(t1_id, txt) values(2,'focus');
    insert into t1(t1_id, txt) values(3,'golf');
    insert into t1(t1_id, txt) values(4,'explorer');
    insert into t1(t1_id, txt) values(5,'corolla');

insert into t2(t2_id, t1_id, price) values(1,1,17000);
insert into t2(t2_id, t1_id, price) values(2,2,16000);
insert into t2(t2_id, t1_id, price) values(3,3,22000);
insert into t2(t2_id, t1_id, price) values(4,4,31000);
insert into t2(t2_id, t1_id, price) values(5,5,17000);


create view t1_view as select * from t1;
create view t2_view as select * from t2;
create view t_stacked_view as 
  select t1_view.txt ,
       t2_view.price ,
         t1_view.t1_id
    from t1_view 
          left join
          t2_view 
            on t1_view.t1_id = t2_view .t1_id
    ;   


--stacked view test
select t1_view.txt ,
       (select t_stacked_view.price 
            from t_stacked_view 
             where t1_view.t1_id = t_stacked_view .t1_id) price
    from t1_view ;

--or better yet, just drop the row level query
select t1_view.txt ,
       t2_view.price
    from t1_view 
          left join
          t2_view 
            on t1_view.t1_id = t2_view .t1_id
    ; 

しかし、ここで疑問が生じます。なぜ、ここで行レベルのクエリを実行しているのですか? 10g はそれらを同じように最適化する必要がありますが、読みやすさ、保守性、および発生しているエラーを具体的に回避するために、以下のようにクエリを記述する方が簡単であることが常にわかっています (常に、3 年後、アプリケーション (db と呼び出し元アプリの両方) で、このエラーを引き起こす条件を持つことはできませんか? 1 つの rouge ステートメントが入り込み、アプリ全体が停止しますか?

    SELECT LV.PRICE,
            c.model_name
FROM LEDGER_VIEW LV
      LEFT /* OR INNER */ JOIN CARS C 
       ON C.MODEL_ID = LV.MODEL_ID
WHERE LV.PRICE < 500
于 2010-09-27T15:03:49.523 に答える
1

RedFilter の回答を使用して、特定の MODEL_ID を持つ車が複数あるかどうかを確認することをお勧めします。

CARS.MODEL_ID が一意であることを完全に確信している場合は、エラー メッセージが LEDGER_VIEW からの選択によって生成されることを意味します。そのため、CARS でサブクエリを使用せずに同等のクエリを実行してみてください。

SELECT LV.PRICE
FROM LEDGER_VIEW LV
WHERE LV.PRICE < 500

それでも同じエラーが表示される場合 (CARS.MODEL_ID が一意の場合は表示されるはずです)、LEDGER_VIEW をデバッグする必要があります。LEDGER_VIEW で複数の行を返すサブクエリと、それが基づいている基礎となるビューを確認します。

ビューに基づいてビューを作成することは、ほとんどの形式の SQL で可能ですが、通常は悪い考えです。まさにこの理由からです。

于 2010-09-27T15:03:58.400 に答える
0

次のように、rownum = 1を追加して、サブクエリに単一の結果を返すように強制してみてください。

SELECT LV.PRICE,
(SELECT C.MODEL_NAME FROM CARS C WHERE C.MODEL_ID = LV.MODEL_ID AND ROWNUM = 1) as MODEL_NAME
FROM LEDGER_VIEW LV
WHERE LV.PRICE < 500

それはおそらく機能し、機能する場合は、サブクエリが複数の行を返すことがわかります。これは、エラーコードによって判断されます。もちろん、これは解決策ではないため、実際に問題を解決するには、carsテーブルのデータを修正する必要がある場合があります。そのままにしてrownum=1にすると、model_idが再度複製された場合にエラーが解消され、問題に気付くことができなくなります。

于 2010-09-27T20:44:33.363 に答える