oracle plsql sélectionner pivot sans SQL dynamique de groupe par [fermée]
Question
A qui il peut répondre, Nous aimerions utiliser la fonction SELECT avec l'option PIVOT à un SGBD Oracle 11g R2. Notre requête est comme:
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));
Comme on le voit, XML est commentée, si l'exécution en XML PIVOT donne la sortie correcte au format XML, mais nous sommes tenus d'obtenir les données sous forme de données de pivot sans mise en forme, mais cette phrase jette l'erreur: ORA-00936: expression manquant
Toutes les résolutions ou les idées seraient les bienvenues,
Cordialement
------------- sale mais proc de travail est inférieure à ------------------------
mise à jour par la procédure 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;
La solution 2
la procédure modifiée à 17.01.2011 est sale mais travail, les curseurs en boucle devrait changer, mieux err. la manipulation de la sql dynamique (actuellement sans pareil), va essayer de l'améliorer quand eu le temps. Merci à tous pour votre aide.
Autres conseils
Je n'ai pas une instance Oracle 11 est disponible pour moi maintenant (PIVOT
est nouveau dans Oracle 11), donc je ne peux que spéculer. Je suppose que le --
a fini de commenter tout ce qui suit le pivot
, et Oracle vous a donné une erreur « manque d'expression » parce qu'il attendait de trouver quelque chose après pivot
. Avez-vous essayé commentant xml
en l'entourant avec /*
et */
au lieu de mettre --
avant qu'il ne?
Si vous utilisez cette requête de Java, par exemple, alors je vous attendre à obtenir une erreur « expression manquante » si vous avez tenté d'exécuter le SQL dans la chaîne suivante:
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))";
Parce que cette chaîne SQL se concaténée en une seule ligne, la --
devant xml
provoquera Oracle d'ignorer tout dans la requête après.
EDIT : Dans la procédure que vous avez ajouté, ce qui me préoccupe est cette partie (en abrégé):
v_sql := 'begin
select * from ...;
end;';
open DENEME for
select v_sql from dual;
Je ne comprends pas pourquoi vous utilisez BEGIN
et END
au sein v_sql
. Essayez de les supprimer.
En outre, prendre soin de ne pas laisser un point-virgule final dans votre chaîne d'instruction SQL. Ce qui suit donnera une erreur de ORA-00911: invalid character
si vous essayez de l'exécuter en utilisant EXECUTE IMMEDIATE ou suchlike:
v_sql := 'select * from dual;'; /* note the semicolon inside the string */
mais ce qui suit sera OK:
v_sql := 'select * from dual';
Enfin, il semble que vous voulez retourner les résultats de cette requête SQL, pas la requête elle-même comme une chaîne. Le remplacement de votre déclaration de open DENEME for ...
avec ce qui suit devrait faire ce que vous voulez:
open DENEME for v_sql;
EDIT 2 : Dans votre procédure, il y a un appel en commentaire à DBMS_OUTPUT.PUT_LINE. Avez-vous vérifié que le SQL généré ici est correcte? En particulier, vous êtes sûr qu'aucune des valeurs utilisées pour former v_query_items
et v_pivot_items
ont des caractères '
en eux?
Il est peut-être qu'il ya un problème à l'aide PIVOT
avec SQL dynamique. Je ne sais pas, et ne peut pas aider beaucoup plus parce que je n'ai pas accès à Oracle 11 ici. Avez-vous encore des erreurs si vous simplifiez le SQL à une requête beaucoup plus petite, mais qui a encore PIVOT
en elle? En d'autres termes, trouver une simple requête PIVOT
que les travaux (par exemple, vous pouvez l'exécuter avec succès dans Developer ou suchlike SQL), écrire une procédure comme la suivante, et voyez si vous obtenez tout retour de données de celui-ci:
CREATE OR REPLACE PROCEDURE dynamic_pivot_test(
results OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN results FOR 'SELECT ...'; /* put the PIVOT query here. */
END;
/