SQL0206N «SQLSTATE» недопустим в контексте, где он используется.SQLSTATE = 42703 - PullRequest
1 голос
/ 31 января 2012

следующий код при выполнении с использованием db2 -td @ ​​-f./sql/update_product.sql выдает ошибку как: SQL0206N «SQLSTATE» недопустим в контексте, где он используется.НОМЕР ЛИНИИ = 53.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 
  @

Ответы [ 2 ]

3 голосов
/ 22 июля 2014

Хранимая процедура сообщает вам, что вы не объявили переменную SQLSTATE. Несмотря на то, что SQLSTATE - это специальная переменная, значение которой неявно поддерживается базой данных (интерпретатором хранимых процедур или компилятором), вам все равно нужно объявить ее, когда вы хотите ее использовать:

DECLARE SQLSTATE CHAR(5);

Кстати, то же самое относится и к переменной SQLCODE:

DECLARE SQLCODE INTEGER DEFAULT 0;

Вот документация для более старой версии, но она все равно должна применяться.

Важно : значение SQLSTATE применяется (только) к непосредственно предшествующему оператору. Если вы используете обработчик для обработки предупреждений и исключений, и вы хотите использовать значение SQLSTATE в обработчике, а ваш обработчик состоит из более чем одного оператора, вам нужно сохранить значение SQLSTATE, прежде чем делать что-либо еще.

Цикл WHILE в вашем примере работает только до тех пор, пока последний оператор в теле цикла является тем, который определяет значение SQLSTATE. Альтернативой является использование выделенного логического done и, в зависимости от вашей логики, continue handler for not found, который устанавливает его в ИСТИНА.

0 голосов
/ 31 января 2012

Насколько я могу судить, SQLSTATE не существует в том формате, о котором вы думаете; и как минимум, вы не можете использовать его для управления выполнением вашего цикла (здесь) в любом случае. Вместо этого вам нужно использовать вещи, называемые HANDLER s (CONTINUE и EXCEPTION, как минимум) - SQLSTATE доступно вне вся процедура (... в значительной степени).

Кроме того, вы используете цикл без заметной выгоды - вся процедура может быть переписана на пару стандартных INSERT s. Вам нужно будет завершить процедуру, но ваши заявления составляют:

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 был создан для выполнения работы «Set», поэтому пишите операторы в этой парадигме. В случаях необходимы циклы, но это не один из них.

...