2012-01-30 161 views
1

db2 -td @ -f./sql/update_product.sql を使用して次のコードを実行すると、次のようなエラーが返されます。 SQL0206N "SQLSTATE"は使用されているコンテキストでは無効です。 LINE NUMBER = 53。 SQLSTATE = 42703SQL0206N "SQLSTATE"は、使用されているコンテキストでは無効です。 SQLSTATE = 42703

...

SET SERVEROUTPUT ON 
    @ 
    CREATE OR REPLACE PROCEDURE UPLOADPRODUCTATTRIBUTES 
    BEGIN 
    DECLARE v_eisidentifier VARCHAR(100); 
    DECLARE v_categoryGuid DECIMAL(19,0); 
    DECLARE v_localeGuid DECIMAL(19,0); 
    DECLARE v_realmGuid DECIMAL(19,0); 
    DECLARE v_catchingPhrase VARCHAR(120) ; 
    DECLARE v_genericName VARCHAR(80); 
    DECLARE v_ingredients VARCHAR(900); 
    DECLARE v_quantity VARCHAR (60); 
    DECLARE v_dose VARCHAR(40); 
    DECLARE v_nutritionFacts VARCHAR (900); 
    DECLARE v_productDescription VARCHAR(900); 
    DECLARE v_recommendedFor VARCHAR(200); 
    DECLARE v_promotionMessage VARCHAR(200); 
    DECLARE v_message VARCHAR (4500); 
    DECLARE v_proudctGuid DECIMAL(19,0); 
    DECLARE C1 CURSOR FOR 
SELECT 
     EISIDENTIFIER, 
     CATEGORY_GUID, 
     LOCALEGUID, 
     REALMGUID, 
     CATCHING_PHRASE, 
     GENERIC_NAME, 
     INGREDIENTS, 
     QUANTITY, 
     DOSE, 
     NUTIRITION_FACTS, 
     PRODUCT_DESCRIPTION, 
     RECOMMENDED_FOR, 
     PROMOTION_MESSAGE, 
     MESSAGE 
    FROM 
     TEMP_UPLOAD_PRODUCT_ATTRIBUTES; 

     OPEN C1; 
     FETCH C1 into v_eisidentifier, 
         v_categoryGuid, 
         v_localeGuid, 
         v_realmGuid, 
         v_catchingPhrase, 
         v_genericName, 
         v_ingredients, 
         v_quantity, 
         v_dose, 
         v_nutritionFacts, 
         v_productDescription, 
         v_recommendedFor, 
         v_promotionMessage, 
         v_message 
     ; 
     WHILE (SQLSTATE = '00000') 
     DO 
      IF EXISTS (SELECT 1 FROM PRD_PRODUCT WHERE EISIDENTIFIER = v_eisidentifier) 
      THEN 
       SELECT GUID INTO v_productGuid FROM PRD_PRODUCT WHERE EISIDENTIFIER = v_eisidentifier; 

       UPDATE PRD_PRODUCT_L10N 
       SET CATEGORY_GUID = v_categoryGuid, 
        REALMGUID = v_realmGuid, 
        CATCHING_PHRASE =v_catchingPhrase, 
        GENERIC_NAME =v_genericName, 
        INGREDIENTS =v_ingredients, 
        QUANTITY=v_quantity, 
        DOSE=v_dose, 
        NUTIRITION_FACTS=v_nutritionFacts, 
        PRODUCT_DESCRIPTION=v_productDescription, 
        RECOMMENDED_FOR=v_recommendedFor, 
        PROMOTION_MESSAGE=v_promotionMessage, 
        MESSAGE=v_message 
       WHERE PRODUCTGUID =v_proudctGuid and LOCALGUID =v_categoryGuid; 

       IF NOT EXISTS (SELECT 1 FROM PRD_PRODUCT_CATEGORY WHERE CATEGORY_GUID=v_categoryGuid AND PRODUCT_GUID=v_productGuid) 
       THEN 
        INSERT INTO PRD_PRODUCT_CATEGORY (CATEGORY_GUID, PRODUCT_GUID) VALUES (v_categoryGuid,v_productGuid); 
       ELSE 
        -- do nothing 
       END IF; 
      ELSE 
       -- INSERT INTO --- should not be the case.... 
      END IF; 


      FETCH C1 into v_productGuid,  
         v_categoryGuid, 
         v_localeGuid, 
         v_realmGuid, 
         v_catchingPhrase, 
         v_genericName, 
         v_ingredients, 
         v_quantity, 
         v_dose, 
         v_nutritionFacts, 
         v_productDescription, 
         v_recommendedFor, 
         v_promotionMessage, 
         v_message 
      ; 
     END WHILE; 
    CLOSE c1;   
    END 
    @ 

答えて

0

としての近くに私が言うことができるよと、SQLSTATEは、あなたが考えているフォーマットには存在しません助けてください。とにかく、ループ実行を制御するために、これを使うことはできません。代わりに、あなたは(最低でも、CONTINUEEXCEPTIONHANDLER Sと呼ばれるものを使用する必要がある - SQLSTATE全体手順(...ほとんど)が利用可能です。

これ以外にもループを使用しているため、何も分かりません。手順全体を標準の2つのINSERTに書き直すことができます。 、どのくらい(なぜならそうがはるかに速くなるようにオプティマイザの作品は、これらがている方法により、

UPDATE Prd_Product_L10N as a 
SET (category_guid, realmGuid, catching_phrase, 
    generic_name, ingredients, quantity, dose, 
    nutrition_facts, product_description, recommended_for, 
    promotion_message, message) = 
       (SELECT b.category_guid, b.realmGuid, b.catching_phrase, 
         b.generic_name, b.ingredients, b.quantity, b.dose, 
         b.nutrition_facts, b.product_description, b.recommended_for, 
         b.promotion_message, b.message 
       FROM Temp_Upload_Product_Attributes as b 
       JOIN Prd_Product as c 
       ON c.eisIdentifier = b.eisIdentifier 
       AND c.guid = a.productGuid 
       WHERE b.category_guid = a.localGuid) 

WHERE EXISTS (SELECT '1' 
       FROM Temp_Upload_Product_Attributes as b 
       JOIN Prd_Product as c 
       ON c.eisIdentifier = b.eisIdentifier 
       AND c.guid = a.productGuid 
       WHERE b.category_Guid = a.localGuid); 

INSERT INTO Prd_Product_Category (category_guid, product_guid) 
SELECT a.localGuid, a.productGuid 
FROM Prd_Product_L10N as a 
WHERE NOT EXISTS (SELECT '1' 
        FROM Prd_Product_Category as b 
        WHERE b.category_guid = a.localGuid 
        AND b.product_guid = a.productGuid); 

はそれを注意してください:あなたは手続きを終える必要があるが、あなたの文の量によアナライザを動かさなくても答えることができない場合でも)。それは直面する:ループとカーソルを使用してではない SQLは本当にどのように使用するつもりです - SQLは、 '設定'作業のために作成されたので、そのパラダイムに文を書く。 はループが必要な場合はですが、これはその1つではありません。

3

SQLSTATE変数を宣言していないことを示すストアドプロシージャがあります。 SQLSTATE値暗黙的にデータベース(ストアドプロシージャインタプリタやコンパイラ)によって維持されている、あなたはまだあなたがそれを使用したいときにそれを宣言する必要がある特殊変数、であるにもかかわらず :ところで

DECLARE SQLSTATE CHAR(5); 

、同じことは、SQLCODE変数のために行く:古いバージョンのための

DECLARE SQLCODE INTEGER DEFAULT 0; 

Here's the documentation、それはまだ適用されるべきです。

重要:SQLSTATEの値は、直前のステートメントに(のみ)適用されます。 ハンドラを使用して警告と例外を処理し、ハンドラでSQLSTATE値を使用し、ハンドラが複数の文で構成されている場合は、他の操作を行う前にSQLSTATE値を保存する必要があります。

例のWHILEループは、ループ本体の最後のステートメントがSQLSTATE値を決定するステートメントである場合に限り機能します。別の方法として、専用のブール値doneを使用し、ロジックに応じてcontinue handler for not foundにTRUEを設定します。

+0

Good find。これは質問に答えます(私が書いたものよりも直接的に)。個人的には、これはまだOPが試みていることをやるには貧弱な方法だと思います。少なくとも、 'SQLSTATE' /' SQLCODE'値はあなたが実際に気にしない警告を示すかもしれないので、 '00000'値は通常厳密にコード化されるべきではありません。 –

+0

私はすべての点数に同意します。設定や反復のアプローチが優れているかどうかは、多くの側面、スキル、可読性、パフォーマンスに左右されます。 –

関連する問題