Oracle PLSQL seleccionar pivote sin SQL dinámico al grupo por [cerrada]
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;
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;
/