1

私はコーディングが初めてで、カーソルとループを使用して以下の表を更新しようとしています (行番号関数に依存していません)。私のテーブルは、列として id とモデルを持つ Cars です。問題は、重複した番号を持つ id 列を更新しようとしていることです。たとえば、テーブルは次のようになります。IDを主キーにしたい。

ID    MODEL 
1    Civic 
1    Accord 
3    Buick 
3    Corolla 
3    Prius 
3    Saab 

以下で試しましたが、すべての値が変更されるだけです。私は何を間違っていますか?このループは何をしているのですか?

DECLARE 
    ids number; 
    models varchar2 (50); 
    previous_id number := 0; 
    new_id number :=0; 
    cursor getRow is select * from CARS; 

BEGIN  
    open getRow; 
    fetch getRow into ids, models; 
    previous_id := ids; 
    loop 
        fetch getRow into ids, models; 
        if getRow%found 
        then  
            new id := previous_id +1; 
            if ids = previous_id 
            then  
                  update CARS 
                set ID = new_id 
                where ID = previous_id; 
            else  
                previous_id := ids;     
            end if; 
            else 
                exit; 
        end if; 
    end loop; 
    close getRow; 
END;
4

1 に答える 1

2

これはあなたの目的を達成するための最も簡単な方法です:

update cars
set id = rownum;

これにより、IDが一意の単調に増加する数値に設定されます。

あなたはコーディングに不慣れだと言っているので、おそらくそれが簡単な答えを使いたくない唯一の理由ですか?

とにかく、コードが機能しない理由は、IDのセットを選択してから、それらのバッチを更新しているためです。更新が現在の行に影響を与えていると思いますが、そうではありません。共有IDですべての行を更新します。また、NEW_IDとPREVIOUS_IDに関するロジックは奇抜です。つまり、1つの変数だけを使用して連続性を維持する必要があります。

ループの使用を主張する場合は、FOR UPDATEカーソルを使用し、WHERECURRENTOFを使用して現在の行だけを更新する必要があります。

DECLARE 
    ids number; 
    models varchar2 (50); 
    previous_id number :=0; 
    cursor getRow is 
       select * from CARS
       for update of id; 

BEGIN  
    open getRow; 
    fetch getRow into ids, models; 
    loop 
        if getRow%found 
        then  
            if ids = previous_id 
            then  
                previous_id := previous_id +1; 
                update CARS 
                set ID = new_id 
                where current of getRow; 
            else  
                previous_id := ids;     
            end if; 
        else 
            exit; 
        end if; 
        fetch getRow into ids, models; 
    end loop; 
    close getRow; 
END;

しかし、これは純粋なSQLソリューションと比較してコードが多すぎます。また、パフォーマンスも大幅に低下します。これがPL/SQLを自分で学ぶためのおもちゃの練習である場合、どちらも重要ではありませんが、実際のアプリケーションでコーディングするようなものではありません。

于 2012-10-14T14:03:27.103 に答える