2011-02-18 3 views
2

Une requête complexe génère un rapport. La requête comporte plusieurs sous-requêtes qui génèrent une table à trois colonnes pour différents produits. Chaque sous-requête renvoie une ligne. Toutes les lignes retournées doivent ensuite être réunies. Mais il y a une exigence. S'il n'y a pas de lignes de résultats pour une sous-requête, nous devons quand même inclure le produit correspondant dans le rapport final, mais spécifiez que Trades_Count est égal à zéro.Utilisation de variables dans le script Oracle

Je peux y parvenir en utilisant un ensemble de variables. Le code suivant fonctionnera parfaitement dans MS SQL Server:

DECLARE @PRODUCT_NAME_1 nvarchar(100); 
DECLARE @OFFER_VALID_DATE_1 datetime; 
DECLARE @TRADES_COUNT_1 int; 

DECLARE @PRODUCT_NAME_2 nvarchar(100); 
DECLARE @OFFER_VALID_DATE_2 datetime; 
DECLARE @TRADES_COUNT_2 int; 

--Product 1 
select @PRODUCT_NAME_1 = PRODUCT_NAME, @OFFER_VALID_DATE_1 = MAX(EXPIRY_DATE), @TRADES_COUNT_1 = COUNT(DEAL_NUMBER) 
from (
     --Data extractions with several joins goes here.... 

) as TempTable1 
GROUP BY PRODUCT_NAME 


--Product 2 
select @PRODUCT_NAME_2 = PRODUCT_NAME, @OFFER_VALID_DATE_2 = MAX(EXPIRY_DATE), @TRADES_COUNT_2 = COUNT(DEAL_NUMBER) 
from (
     --Data extractions with several joins goes here.... 
) as TempTable2 
GROUP BY PRODUCT_NAME 


SELECT ISNULL(@PRODUCT_NAME_1,'Product 1') AS PRODUCT_NAME, @OFFER_VALID_DATE_1 AS MAX_MATURITY, ISNULL(@TRADES_COUNT_1,0) 
UNION 
(
SELECT ISNULL(@PRODUCT_NAME_2,'Product 2') AS PRODUCT_NAME, @OFFER_VALID_DATE_2 AS MAX_MATURITY, ISNULL(@TRADES_COUNT_2,0) 
) 

Je pense que je ne l'ai pas utilisé quoi que ce soit T-SQL spécifique, mais pur ANSI-SQL (je ne suis pas sûr à 100% si).

Il s'agit donc de ne fonctionnant pas dans Oracle. Tout d'abord, il ne nécessite qu'un seul mot-clé DECLARE. Ensuite, cela me force à utiliser Begin ... Fin de la portée de l'exécution. Ensuite, il ne me permet pas d'assigner des variables comme je le fais (voir l'exemple ci-dessus) - J'ai besoin d'utiliser l'instruction "Select INTO" à la place. Une fois tous les calculs effectués, il ne me permet pas de sélectionner des valeurs à partir de variables locales. Zut.

Est-ce que quelqu'un sait comment le faire fonctionner dans Oracle?

Merci!

Répondre

7

PL/SQL est différent de t-sql, j'ai fait un changement avec quelques commentaires pour vous, mais certainement regarder les liens d'Andy. Cela a été couru en libre SQL Developer Oracle (qui a aussi une « traduction Handler Scratch (Outils> Migration> Traduction Handler Scratch) qui peuvent être utiles

--this creates a refcursor to allow us to simply print the results 
var refc refcursor 
/

declare --here we declare our variables 
    product_name_1 varchar2(15) ; 
    offer_valid_date_1 date ; 
    trade_count_1 number ; 
    product_name_2 varchar2(15) ; 
    offer_valid_date_2 date ; 
    trade_count_2 number ;  
begin 
    begin --this creates a block so we may handle any exceptions just to this 
      select PRODUCT_NAME, MAX(EXPIRY_DATE), COUNT(DEAL_NUMBER) 
      into product_name_1 , offer_valid_date_1 , trade_count_1 
      --in oracle you select INTO, not var=COL 
     from (
       --Data extractions with several joins goes here.... 
       select 
        123 PRODUCT_NAME,  
        sysdate EXPIRY_DATE,  
        5 DEAL_NUMBER 
       from dual --this is a 'fake' table to generate some data for testing 

     ) TempTable1 --drop the "as" 
     GROUP BY PRODUCT_NAME ; 
    exception --if not data is found, then this error is thrown 
       --if multiple values are thrown an error will also be thrown (not caught here) 
    when no_data_found then 
     product_name_1 := null ; --note, to do a var = , we use "var := value;" 
     offer_valid_date_1 := null; 
     trade_count_1 := null; 
    end ; 
    begin 
      select PRODUCT_NAME, MAX(EXPIRY_DATE), COUNT(DEAL_NUMBER) 
      into product_name_2 , offer_valid_date_2 , trade_count_2 
      --in oracle you select INTO, not var=COL 
     from (
       --Data extractions with several joins goes here.... 
       select 555 PRODUCT_NAME, sysdate EXPIRY_DATE, 6 DEAL_NUMBER 
       from dual 

     ) TempTable2 -- drop the "as" 
     GROUP BY PRODUCT_NAME ; 
    exception --if not data is found, then this error is thrown 
       --if multiple values are thrown an error will also be thrown (not caught here) 
    when no_data_found then 
     product_name_2 := null ; 
     offer_valid_date_2 := null; 
     trade_count_2 := null; 
    end ; 

    open :refc for --you cannot just have a select statement, you must "open" a cursor for it  
    --oracle IsNull is NVL (or NVL2 or you can do a case or decode...) 
    SELECT nvl(PRODUCT_NAME_1,'Product 1') AS PRODUCT_NAME 
      , OFFER_VALID_DATE_1 AS MAX_MATURITY 
      , nvl(TRADE_COUNT_1,0) 
     FROM DUAL --you also must have a table, DUAL is an oracle table for this tasks 
     UNION 
    SELECT nvl(PRODUCT_NAME_2,'Product 2') AS PRODUCT_NAME 
      , OFFER_VALID_DATE_2 AS MAX_MATURITY 
      , nvl(TRADE_COUNT_2,0) 
    FROM DUAL; 

end ; 
/

--now print the results, if you did this in a proc you would simple have this as an output 
print refc; 

------------- 
PRODUCT_NAME MAX_MATURITY    NVL(:B1,0)    
-------------------------------------- ---------------------- 
123   18.FEB.2011 08:43   1      
555   18.FEB.2011 08:43   1      

concepts Oracle utilisé ici. Dual Table, NVL, Variables , pl/sql Exception

et regardez ce http://www.dba-oracle.com/t_convent_sql_server_tsql_oracle_plsql.htm

+0

Merci beaucoup. il est très inspite complexe, ça marche! :) –

1

PL/SQL formate les blocs procéduraux différemment de T-SQL.

Vous souhaitez utiliser la structure suivante:

DECLARE 
    astring varchar2(1000); 
    anumber number; 

BEGIN 
    my SQL code here... 
END; 

Vous n'utilisez pas le @ soit en PL/SQL. Utilisez simplement les noms de variables directement.