Использование переменных в сценарии Oracle - PullRequest
2 голосов
/ 18 февраля 2011

Существует сложный запрос, который генерирует отчет.Запрос имеет несколько вложенных запросов, которые генерируют таблицу из 3 столбцов для различных продуктов.Каждый подзапрос возвращает одну строку.Все возвращаемые строки должны быть объединены.Но есть одно требование.Если для подзапроса нет строк результата, нам все равно нужно включить соответствующий продукт в окончательный отчет, но указать, что Trades_Count равен нулю.

Я могу добиться этого, используя набор переменных.Следующий код будет отлично работать в 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)
)

Я думаю, что я не использовал ничего специфичного для T-SQL, но чистый ANSI-SQL (хотя я не уверен на 100%).

Так что не работает в Oracle.

Прежде всего требуется только одно ключевое слово DECLARE.Тогда это заставляет меня использовать Begin ... End end scope.Тогда это не позволяет мне назначать переменные, как я (см. Пример выше) - мне нужно вместо этого использовать оператор «Выбрать INTO».После того, как все вычисления сделаны, это не позволяет мне выбирать значения из локальных переменных.Черт.

Кто-нибудь знает, как заставить его работать в Oracle?

Спасибо!

Ответы [ 2 ]

7 голосов
/ 18 февраля 2011

PL / SQL отличается от t-sql, я внес некоторые изменения для вас, но обязательно посмотрите ссылки Энди. Он был запущен в бесплатном Oracle Developer (который также имеет «Обработчик царапин перевода» (инструменты> Миграция> Обработчик царапин перевода), который может быть полезен.

--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, используемые здесь: Двойной стол , NVL , Переменные , pl / sql Исключение

и посмотрите на это http://www.dba -oracle.com / t_convent_sql_server_tsql_oracle_plsql.htm

1 голос
/ 18 февраля 2011

PL / SQL форматирует процедурные блоки не так, как T-SQL.

Вы захотите использовать следующую структуру:

DECLARE
    astring varchar2(1000);
    anumber number;

BEGIN
   my SQL code here...
END;

Вы не используете @ либо в PL/ SQL.Просто используйте имена переменных напрямую.

...