2

レポートを生成する複雑なクエリがあります。クエリには、さまざまな製品の3列のテーブルを生成するいくつかのサブクエリがあります。各サブクエリは1行を返します。次に、返されたすべての行を結合する必要があります。ただし、要件が1つあります。サブクエリの結果行がない場合は、とにかく対応する商品を最終レポートに含める必要がありますが、Trades_Countがゼロに等しいことを指定します。

これは、変数のセットを使用して実現できます。次のコードは、MSSQLServerで完全に機能します。

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

私はT-SQL固有のものは何も使用していないと思いますが、純粋なANSI-SQLを使用しています(100%確実ではありませんが)。

したがって、これはOracleでは機能しません。

まず、DECLAREキーワードが1つだけ必要です。次に、Begin…End実行スコープを使用するように強制します。次に、私が行うように変数を割り当てることができません(上記の例を参照)–代わりに「SelectINTO」ステートメントを使用する必要があります。すべての計算が完了した後、ローカル変数から値を選択することはできません。ヘック。

Oracleで動作させる方法を知っている人はいますか?

ありがとう!

4

2 に答える 2

7

PL/SQL は t-sql とは異なります。いくつかのコメントを追加して変更を行いましたが、Andy からのリンクを確認してください。これは、オラクルの無料の SQL Developer で実行されました (「Translation Scratch Handler (tools>Migration>Translation Scratch Handler) もあり、役に立つ可能性があります。

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

ここで使用される Oracle の概念: Dual TableNVLVariablespl/sql Exception

この http://www.dba-oracle.com/t_convent_sql_server_tsql_oracle_plsql.htmを見てください

于 2011-02-18T13:35:18.483 に答える
1

PL/SQL は、手続き型ブロックを T-SQL とは異なる形式でフォーマットします。

次の構造を使用する必要があります。

DECLARE
    astring varchar2(1000);
    anumber number;

BEGIN
   my SQL code here...
END;

PL/SQL でも @ は使用しません。変数名を直接使用するだけです。

于 2011-02-18T13:17:47.070 に答える