Pregunta

A quien pueda responder a, Nos gustaría utilizar la función SELECT con opción de pivote en un 11g R2 Oracle DBMS. Nuestra consulta es como:

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));

Como se puede ver, XML está comentado, si carrera como XML PIVOT se da la salida correcta en formato XML, sino que es necesario para obtener los datos como datos sin formato de pivote, pero esta frase lanza de error: ORA-00936: falta una expresión

Cualquier resolución o ideas serían bien recibidos,

Saludos

------------- sucio, pero proc de trabajo está por debajo ------------------------

actualizado el procedimiento mediante el 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;
¿Fue útil?

Solución 2

el procedimiento editado al 17.01.2011 es sucio, pero de trabajo, de enlace cursores debe cambiar, mejor err. manejo para el SQL dinámico (actualmente insuperable), va a tratar de mejorarlo cuando tiene tiempo. Gracias a todos por su ayuda.

Otros consejos

No tengo una instancia de Oracle 11 disponibles para mí ahora (PIVOT es nuevo en Oracle 11) por lo que sólo puedo especular. Mi conjetura es que el -- ha acabado comentando todo después de la pivot, y Oracle le ha dado un error de 'falta de expresión', ya que se esperaba encontrar algo después de pivot. ¿Ha intentado comentando xml rodeándolo con /* y */ en vez de poner -- antes de que?

Si se ejecuta esta consulta desde Java, por ejemplo, entonces yo esperaría que usted pueda obtener un error de 'falta de expresión' si usted ha intentado ejecutar el SQL en la siguiente cadena:

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))";

Debido a que esta cadena SQL se concatenan en una línea, la -- frente a xml hará que Oracle para ignorar todo en la consulta después de ella.

Editar : En el procedimiento que ha añadido, lo que me preocupa es esta parte (abreviado):

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

open DENEME for
select v_sql from dual;

No entiendo por qué estás usando BEGIN y END dentro v_sql. Pruebe la eliminación de ellos.

Además, tenga cuidado de no dejar un punto y coma final en su serie de la sentencia SQL. A continuación se dará un error ORA-00911: invalid character si intenta ejecutarlo utilizando EXECUTE IMMEDIATE o cosas por el estilo:

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

pero el siguiente será en Aceptar:

v_sql := 'select * from dual';

Por último, parece que desea devolver los resultados de esta consulta SQL, no la propia consulta como una cadena. El cambio de su declaración open DENEME for ... con el siguiente debe hacer lo que quiera:

open DENEME for v_sql;

EDIT 2 : En el procedimiento, se hace un llamado a cabo comentado DBMS_OUTPUT.PUT_LINE. ¿Ha verificado que el SQL generado aquí es correcta? En particular, ¿está seguro de que ninguno de los valores utilizados para formar v_query_items y v_pivot_items tiene caracteres ' en ellos?

Puede ser que hay un problema con el uso de PIVOT SQL dinámico. No sé, no puedo ayudar mucho más, porque no tengo acceso a Oracle 11 aquí. ¿Todavía se producen errores si se simplifica el SQL para una consulta mucho más pequeño, pero que todavía tiene PIVOT en ella? En otras palabras, encontrar una consulta PIVOT simple que funciona (por ejemplo, se puede ejecutar con éxito en SQL Developer o cosas por el estilo), escribir un procedimiento como el siguiente, para ver si tiene alguno de regreso datos de ella:

CREATE OR REPLACE PROCEDURE dynamic_pivot_test(
  results OUT SYS_REFCURSOR
)
AS
BEGIN
  OPEN results FOR 'SELECT ...'; /* put the PIVOT query here. */
END;
/
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top