2013-08-07 4 views
2

В Oracle у меня есть много хранимых процедур с использованием пакета, который в основном хранит (инкапсулирует) и инициализирует все переменные, используемые этими процедурами. В пакете также есть одна функция, которая заботится об инициализации всех ее переменных пакета.Как перевести пакет Oracle на SQL Server?

Мой вопрос: как перенести это на SQL Server?

Моя первая попытка состоит в том, чтобы объявить все переменные пакета и использовать их как параметры OUTPUT для процедуры инициализации, но тогда мне нужно объявлять эти переменные снова и снова в каждой процедуре, используя их (и есть много их в пакете). Есть ли лучший (и DRY) способ сделать это на SQL Server?

Некоторый код, чтобы объяснить это:

ORACLE:

Пакет:

create or replace 
PACKAGE MYPARAMS AS 

    /** 
    param container 
    */ 
    type rc_params is record 
    (
    var1 varchar2(30), 
    var2 integer 
); 
    /** 
    init param container 
    use: v_params rc_pkp_plan_params := MYPARAMS.f_get_params(initvar) 
    */ 
    function f_get_params(initvar number) return rc_params; 

END MYPARAMS; 
/

Пакет тела:

CREATE OR REPLACE 
PACKAGE BODY MYPARAMS AS 

    function f_get_params(initvar number) return rc_params AS 
    retval rc_params; 
    BEGIN 
    retval.var1 := 'MY_VAR1'; 
    retval.var2 := initvar; 
    return retval; 
    END f_get_params; 

END MYPARAMS; 
/

Некоторые примеры использования:

declare 
    initvar integer := 22; 
    v_params MYPARAMS.rc_params := MYPARAMS.f_get_params(initvar); 
begin 
    dbms_output.put_line(v_params.var1 || ' initialized by ' || v_params.var2); 
end; 

SQL Server:

if exists (select * from sysobjects where id = object_id('f_get_params')) 
    drop procedure f_get_params 
go 
create procedure f_get_params(
    @initvalue integer, 
    @var1 varchar(30) OUTPUT, 
    @var2 integer OUTPUT 
) 
as 
    set @var1 = 'MYVAR1' 
    set @var2 = @initvalue 
go 

-- this block i would like to avoid: 
declare 
    @initvalue integer = 33, 
    @var1 varchar(30), 
    @var2 integer 

exec f_get_params @initvalue, @var1 OUTPUT, @var2 OUTPUT 
print @var1 + ' initialized by ' + convert(varchar(2), @var2) 

Надежда описание достаточно ясно ...

+0

Вам не нравится 'declare @initvalue integer = 33, var1 varchar (30), @ var2 integer', в частности? –

+0

Да, потому что мне нужны эти вары почти во всех моих процедурах. поэтому я хочу инкапсулировать эти вары и (самое главное для меня) их инициализацию. – Jakob

ответ

2

К сожалению, T-SQL не имеет ничего подобного пакетов Oracle, переменных пакета или структур переменных. О, это так.

Возможно, что вы сделали, это самый простой способ выполнить его в T-SQL, даже если он требует дублирования переменных.

Вы можете использовать таблицу #, т. Е. Создать таблицу #params в f_get_parms, которая содержит все переменные, а затем использовать эту # таблицу во всех других procs для их извлечения. Недостатком является то, что вы все равно должны объявить переменные в вызывающих процедурах или использовать DML для доступа к столбцам в таблице #, что является намного более громоздким, чем их использование в качестве переменных.

Другой способ, которым я использовал ранее, - использовать XML для передачи нескольких переменных, но рассматривать их как один. Это еще более громоздко для доступа к значениям, чем в переменных, но имеет то преимущество, что вы можете использовать функцию вместо процедуры для получения значений.

CREATE FUNCTION dbo.uf_get_params (
    @initvar int 
) 
RETURNS xml 
AS 
BEGIN 
    DECLARE @xml xml, 
      @var1 varchar(30) = 'MYVAR' -- setting value on DECLARE requires SQL2008+ 

    SELECT @xml = (SELECT @var1 AS var1, 
         @initvar AS initvar 
        FOR XML RAW('params')) 

    RETURN @xml 
END 
go 

В вашей вызывающей процедуре, вы бы

DECLARE @params xml = (SELECT dbo.uf_get_parms(12)) 

, чтобы получить параметры, а затем использовать стандартные функции XML/XQuery для извлечения отдельных переменных (атрибутов) из переменной @params XML.

+0

хорошая идея, я не думал о Vartype XML. плохо попробуйте это. – Jakob

+0

Я сделал это, как было предложено, потому что это единственный способ «собрать» вещи в SQL Server – Jakob

Смежные вопросы