oracle plsql выбирает pivot без динамического sql для группировки по [закрыто]

StackOverflow https://stackoverflow.com/questions/4699332

Вопрос

Кому он может отвечать, Мы хотели бы использовать функцию SELECT с опцией PIVOT в СУБД Oracle 11g r2.Наш запрос выглядит следующим образом :

select * from
(SELECT o.ship_to_customer_no, ol.item_no,ol.amount
  FROM t_order o, t_order_line ol
 WHERE o.NO = ol.order_no and ol.item_no in (select distinct(item_no) from t_order_line))
  pivot --xml 
(  SUM(amount) FOR item_no IN ( select distinct(item_no) as item_no_ from t_order_line));

Как можно видеть, XML закомментирован, при запуске как сводный XML он выдает правильный вывод в формате XML, но мы обязаны получать данные как неформатированные сводные данные, но это предложение выдает ошибку :ORA-00936:отсутствующее выражение

Любые резолюции или идеи будут приветствоваться,

С наилучшими пожеланиями

-------------грязный, но работающий процесс приведен ниже------------------------

обновлена процедура по состоянию на 17.01.2011 16:39 GMT :

 PROCEDURE pr_pivot_item_by_ship_to (
      p_location_code             IN       t_customer.location_code%TYPE,
      p_customer_price_group      IN       t_customer.customer_price_group%TYPE,
      p_shipment_date             IN       t_order.shipment_date%TYPE,
      p_fasdat_status             IN       t_order.fasdat_status%TYPE,
      p_order_type                IN       t_order.order_type%TYPE,
      cur_pivot_item_by_ship_to   OUT      sys_refcursor
   )
   IS
      v_sql            VARCHAR2 (15000);
      v_pivot_items    VARCHAR2 (15000) := '';
      v_query_items    VARCHAR2 (15000) := '';
      v_pivot_orders   VARCHAR2 (15000) := '';
      v_continue       INT              := 0;
   BEGIN
      /*GET ORDER NUMBERS*/
      FOR cur_order_loop IN (SELECT DISTINCT (o.NO) AS order_no
                                        FROM t_order o,
                                             vw_customer_with_ship_to_info wwc
                                       WHERE wwc.customer_price_group =
                                                        p_customer_price_group
                                         AND wwc.location_code =
                                                               p_location_code
                                         AND o.shipment_date = p_shipment_date
                                         AND o.fasdat_status = p_fasdat_status
                                         AND o.order_type = p_order_type
                                         AND wwc.NO = o.customer_no)
      LOOP
         v_pivot_orders :=
                ''',''' || TO_CHAR (cur_order_loop.order_no)
                || v_pivot_orders;
         v_pivot_orders := LTRIM (v_pivot_orders, ''',''');
      END LOOP;

      /*USE ORDER NUMBERS TO FIND ITEMS TO PIVOT BY SHIPMENT PLACE*/
      FOR cur_loop IN
         (SELECT DISTINCT (ol.item_no) AS item_no,
                          REPLACE
                             (REPLACE (SUBSTR (i.description, 1, 20), '''',
                                       ''),
                              '"',
                              ' inch'
                             ) AS description
                     FROM t_order_line ol, t_item i
                    WHERE ol.item_no = i.NO
                      AND ol.order_no IN (
                             SELECT DISTINCT (o.NO) AS order_no
                                        FROM t_order o,
                                             vw_customer_with_ship_to_info wwc
                                       WHERE wwc.customer_price_group =
                                                        p_customer_price_group
                                         AND wwc.location_code =
                                                               p_location_code
                                         AND o.shipment_date = p_shipment_date
                                         AND o.fasdat_status = p_fasdat_status
                                         AND o.order_type = p_order_type
                                         AND wwc.NO = o.customer_no))
      LOOP
         v_query_items := ',''' || cur_loop.item_no || '''' || v_query_items;
         v_pivot_items :=
               ','''
            || cur_loop.item_no
            || ''' as "ad_'
            || cur_loop.description
            || '"'
            || v_pivot_items;
      END LOOP;

      v_query_items := LTRIM (v_query_items, ',');
      v_pivot_items := LTRIM (v_pivot_items, ',');
      v_sql :=
            'select * from
       (SELECT wwc.ship_to_customer_no||''-''|| wwc.ship_to_customer_name as "Müst. Adi ('
         || p_order_type
         || ')", ol.item_no,ol.amount
         FROM t_order o, t_order_line ol,vw_customer_with_ship_to_info wwc
        WHERE o.NO = ol.order_no
        and wwc.no = o.customer_no
        and ol.order_no in (
        (SELECT DISTINCT (o.NO) AS order_no
                                            FROM t_order o,
                                                 vw_customer_with_ship_to_info wwc
                                           WHERE wwc.customer_price_group ='''
         || p_customer_price_group
         || '''
                                             AND wwc.location_code =
                                                                   '''
         || p_location_code
         || '''
                                            AND o.shipment_date = '''
         || p_shipment_date
         || '''

                                             AND o.fasdat_status = '
         || p_fasdat_status
         || '
                                             AND o.order_type = '''
         || p_order_type
         || '''
                                             AND wwc.NO = o.customer_no)
         )
        and OL.ITEM_NO in ('
         || v_query_items
         || ')
        )
         pivot
       (  SUM(amount) FOR item_no IN ('
         || v_query_items                                      --v_pivot_items
         || '))';

      --DBMS_OUTPUT.put_line ('TSQL ' || v_sql);
       --      OPEN cur_pivot_item_by_ship_to FOR
        --         SELECT v_sql
        --           FROM DUAL;
      BEGIN
         OPEN cur_pivot_item_by_ship_to FOR v_sql;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            NULL;
         WHEN OTHERS
         THEN
            IF SQLCODE = -936
            THEN
               NULL;
            ELSE
               pck_helper.pr_log_error
                                      (SQLCODE,
                                          'p_shipment_date:'
                                       || p_shipment_date
                                       || ','
                                       || 'cur_pivot_item_by_ship_to err. :'
                                       || SQLERRM,
                                       'pr_pivot_item_by_ship_to'
                                      );
            END IF;
      END;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         NULL;
      WHEN OTHERS
      THEN
         pck_helper.pr_log_error (SQLCODE,
                                     'p_shipment_date:'
                                  || p_shipment_date
                                  || ','
                                  || SQLERRM,
                             'pr_pivot_item_by_ship_to'
                                 );
   END pr_pivot_item_by_ship_to;
END pkg_report;
Это было полезно?

Решение 2

Процедура, отредактированная в 17.01.2011, является грязной, но работающая, петлевые курсоры должны измениться, лучшая ошибка. Обработка для динамического SQL (в настоящее время непревзойденной), попытается улучшить его, когда получите время. Спасибо за вашу помощь.

Другие советы

Сейчас у меня нет доступного экземпляра Oracle 11 (PIVOT является новым в Oracle 11), так что я могу только строить догадки.Я предполагаю, что -- закончилось тем, что я закомментировал все после pivot, и Oracle выдал вам ошибку "отсутствующее выражение", потому что он ожидал найти что-то после pivot.Вы пробовали комментировать xml окружив его /* и */ вместо того, чтобы класть -- до этого?

Если бы вы запускали этот запрос, скажем, из Java, то я бы ожидал, что вы получите ошибку "отсутствует выражение", если вы попытаетесь запустить SQL в следующей строке:

String sql =
  "select * from (SELECT o.ship_to_customer_no, ol.item_no,ol.amount " +
  "FROM t_order o, t_order_line ol " +
  "WHERE o.NO = ol.order_no and ol.item_no in (select distinct(item_no) from t_order_line)) " + 
  "pivot --xml " +
  "( SUM(amount) FOR item_no IN ( select distinct(item_no) as item_no_ from t_order_line))";

Поскольку эта строка SQL объединяется в одну строку, -- перед xml это приведет к тому, что Oracle проигнорирует все в запросе после него.

Редактировать:В процедуре, которую вы добавили, меня беспокоит эта часть (сокращенно).:

v_sql := 'begin
           select * from ...;
          end;';

open DENEME for
select v_sql from dual;

Я не понимаю, почему вы используете BEGIN и END внутри v_sql.Попробуйте удалить их.

Кроме того, следите за тем, чтобы не оставлять завершающую точку с запятой в строке инструкции SQL.Следующее даст ORA-00911: invalid character ошибка при попытке запустить его с помощью EXECUTE IMMEDIATE или подобного:

v_sql := 'select * from dual;'; /* note the semicolon inside the string */

но следующее будет в порядке вещей:

v_sql := 'select * from dual';

Наконец, похоже, что вы хотите вернуть результаты этого SQL-запроса, а не сам запрос в виде строки.Замена вашего open DENEME for ... оператор со следующим текстом должен делать то, что вы хотите:

open DENEME for v_sql;

ПРАВКА 2:В вашей процедуре есть закомментированный вызов DBMS_OUTPUT .PUT_LINE .Вы убедились, что сгенерированный здесь SQL верен?В частности, уверены ли вы, что ни одно из значений, используемых для формирования v_query_items и v_pivot_items иметь ' персонажи в них?

Возможно, существует проблема с использованием PIVOT с помощью динамического SQL.Я не знаю и больше ничем не могу помочь, потому что у меня здесь нет доступа к Oracle 11.Вы все еще получаете ошибки, если упростите SQL до гораздо меньшего запроса, но такого, который все еще имеет PIVOT в нем?Другими словами, найдите простой PIVOT запрос, который работает (например,вы можете успешно запустить его в SQL Developer или подобном), напишите процедуру, подобную следующей, и посмотрите, получите ли вы из нее какие-либо данные обратно:

CREATE OR REPLACE PROCEDURE dynamic_pivot_test(
  results OUT SYS_REFCURSOR
)
AS
BEGIN
  OPEN results FOR 'SELECT ...'; /* put the PIVOT query here. */
END;
/
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top