2015-05-08 2 views
3

У меня есть структура XML, которую я анализирую с помощью OPENXML в хранимой процедуре для извлечения параметров, используемых для выполнения запроса. Эта процедура была базовой процедурой, вызывающей другую хранимую процедуру (процедура 2). Процедура 2 использует конструкцию insert-exec для получения данных из базовой процедуры. Это отлично работает, пока мы вызываем только процедуру 2 или базовую процедуру.Как использовать openxml в пользовательской функции в SQL Server

Моя первая проблема заключается в том, что у меня есть другая процедура (процедура 3), что в настоящее время необходимо, чтобы получить результат от процедуры 2 (мне нужны бизнес-правила, что эта процедура обеспечивает соблюдение), но не может из-за сообщения:

Оператор INSERT EXEC не может быть вложен.

Затем я попытался взять процедуру базы и сделать его таблицу функции, но когда я исполню его, я получаю сообщение:

Только функцию и некоторые расширенные хранимые процедуры могут быть выполнены из внутри функции.

Как мне обойти одну или обе эти проблемы?

EDIT 1 Я в том числе фрагмент кода, чтобы показать процедуру базовой (Процедура 1) и бизнес-требования к процедуры реализации по результатам этой процедуры (процедура 2). Если есть 3-я процедура, которая нуждается в результатах с применением бизнес-правил, мы сталкиваемся с проблемами.

create procedure dbo.p_Proc 
    @Xml xml 
as 
begin 
    set nocount on; 

    declare @l_idoc int 
     , @InfoId int 
     , @InfoTypeId int 
     , @Id int 
     , @Name varchar(50) 
     , @StatusId int 
     , @RoleId int 
     , @XmlBase xml 
     , @l_path varchar(100); 

    declare @T_TABLE table(
     InfoId int 
     , InfoTypeId int 
); 

    declare @T_RESULT table 
    (
     Field1 int 
    , Field2 varchar(50) 
    , Field3 int 
); 

    EXEC sp_xml_preparedocument @l_idoc OUTPUT, @Xml; 

    set @l_path = '/xml/Info';   
    insert into @T_TABLE(InfoId, InfoTypeId) 
    select InfoId, InfoTypeId 
    from OPENXML (@l_idoc, @l_path, 1) 
     with (
     InfoId int './@InfoId' 
     , InfoTypeId int './@InfoTypeId' 
    ); 

    select @InfoId = InfoId 
    , @InfoTypeId = InfoTypeId 
    from @T_TABLE; 

    -- create the XML to call the base widgets 
    select @XmlBase = 
    (
    select * 
     from 
    (
     select t.Id, t.Name, t.StatusId, t.RoleId 
     from @T_TABLE w 
     inner join dbo.T_TABLE2 t 
     on t.InfoId = w.InfoId 
     and t.InfoTypeId = w.InfoTypeId 
    ) b 
    for xml raw('Widget'), root('Xml') 
); 

    -- retrieve widgets from base security 
    insert into @T_RESULT(Field1, Field2, Field3) 
    exec dbo.p_ProcBase @Xml = @XmlBase; 

    -- apply business logic here 


    select w.Field1, w.Field2, w.Field3 
    from @T_RESULT w; 
end; 
go 

create procedure dbo.p_ProcBase 
    @Xml xml = null 
as 
begin 
    set nocount on; 

    declare @l_idoc int 
     , @Id int 
     , @Name varchar(50) 
     , @StatusId int 
     , @RoleId int 
     , @l_path varchar(100); 

    declare @T_Table table(
     Id int 
     , Name varchar(50) 
     , StatusId int 
     , RoleId int 
); 

    EXEC sp_xml_preparedocument @l_idoc OUTPUT, @Xml; 

    set @l_path = '/Xml/Widget';  
    insert into @T_Table(Id, Name, StatusId, RoleId) 
    select Id, Name, StatusId, RoleId 
    from OPENXML (@l_idoc, @l_path, 1) 
     with (
     ProjectId int './@Id' 
     , WidgetTypeName varchar(50) './@Name' 
     , WorkflowStatusId int './@StatusId' 
     , UserRoleId bigint './@RoleId' 
    ); 

    select @Id = w.Id 
    , @Name = w.Name 
    , @StatusId = w.StatusId 
    , @RoleId = w.RoleId 
    from @T_Table w; 

    -- retrieve enabled widgets for which the user has a role in the current workflow state 
    select t.Field1, t.Field2, t.Field3 
    from dbo.T_TABLE t 
    where t.StatusId = @StatusId 
    and t.RoleId = @RoleId; 
end; 
+0

Для использования результата вашей хранимой процедуры вы можете создать временную таблицу или переменную таблицы и вставить в нее результаты;). –

+0

Это даст сообщение: инструкция INSERT EXEC не может быть вложенной. –

ответ

2

Для того, чтобы отправить набор данных (таблицу) между проками, вы должны использовать тип таблицы, хранить выход PROC2 в переменном типе таблицы и добавить только для чтения только параметр типа таблицы для proc3

Сначала вы должны создать тип таблицы для отображения вашего выхода из PROC2:

CREATE TYPE T_RESULT AS TABLE 
(
     Field1 int 
    , Field2 varchar(50) 
    , Field3 int 
); 

в dbo.p_Proc изменения @T_RESULT к:

declare @T_RESULT T_RESULT 

Затем создайте proc3:

CREATE PROCEDURE dbo.proc3 
    @T_RESULT T_RESULT READONLY 
AS 
BEGIN  
    SET NOCOUNT ON 
    INSERT INTO T3(...) 
    SELECT ... FROM @T_RESULT 
END 

Не забудьте добавить READONLY после параметра типа таблицы в прок.

+0

Спасибо за ответ Жюльен. Я закончил создание xml из таблицы и передал XML (казался чище и проще). Я действительно ценю ваш ответ, хотя это правильно. –

+0

параметр таблицы действительно большой и полезный, но если вы можете заставить его работать с переменными xml, это, вероятно, лучше, потому что вы также можете легко выводить его из 1 sp в другой. –

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