Как выбрать xml в 1 хранимой процедуре и передать выбранные узлы в качестве параметров в другую процедуру - PullRequest
0 голосов
/ 07 сентября 2010

У меня есть сохраненный процесс, который вставляет «people». У меня есть документ XML с группой людей, которых я хочу вставить. Я хочу вызвать мой сохраненный процесс, как показано ниже, и ожидать, что сохраненный процесс будет вызываться для каждого человека в xml. Это говорит мне о том, что сохраненный процесс «ожидает параметр @Id» и не работает. @Id - первый параметр, и кажется, что мой синтаксис не разрешен. Есть ли способ сделать это без перебора каждого человека в курсоре? Я использую SQL Server 2005.

EXEC Stored_Procedure_That_Inserts_People
SELECT Node.value('Id[1]', 'Int') AS Id
,Node.value('FirstName[1]', 'varchar(50)') AS FirstName
,Node.value('LastName[1]', 'varchar(50)') AS LastName
,Node.value('MI[1]', 'char(1)') AS MI
FROM @PeopleXML.nodes('/ArrayOfPeople/Person') TempXML (Node)

Для всех, кто интересуется, вот как я реализовал свое решение, основываясь на ответе Тома ниже:

CREATE PROCEDURE [dbo].[ccIU_PersonBulkImport] 
(   
    @PersonXML as xml
)
AS
BEGIN

    SET NOCOUNT ON

    DECLARE 
    @LastName AS varchar(50),
    @FirstName AS varchar(50),
    @MI AS char(1)

        DECLARE People CURSOR FORWARD_ONLY STATIC READ_ONLY FOR 
                SELECT 
                Node.value('FirstName[1]', 'varchar(50)') AS FirstName
                ,Node.value('LastName[1]', 'varchar(50)') AS LastName
                ,Node.value('MI[1]', 'char(1)') AS MI
                FROM @PersonXML.nodes('/ArrayOfPeople/Person') TempXML (Node)

        OPEN People;
        FETCH NEXT FROM People INTO @FirstName,@LastName,@MI
        WHILE (@@FETCH_STATUS = 0)
        BEGIN
            EXEC domIU_People @FirstName,@LastName,@MI -- second stored proc that inserts or updates the person
            FETCH NEXT FROM People INTO @FirstName,@LastName,@MI;
        END
    CLOSE People;
    DEALLOCATE People;

END

Ответы [ 2 ]

2 голосов
/ 07 сентября 2010

Нет.

Вы не можете выполнить итерацию хранимой процедуры, как правило, они могут принимать только объекты в качестве параметров, исключение составляет объект таблицы.

В этом примере SQL попытается вызвать SP и затем запустить select как отдельные события, поэтому вы получаете сообщение об ошибке в отсутствующем параметре.

Вы можете выбрать итерацию по XML и вызвать SP для каждой записи, реорганизовать SP для работы с использованием XML в качестве отдельного параметра и разбить его в процедуре вставки людей или изменить код изsp в логике обработки XML.

1 голос
/ 07 сентября 2010

Если хранимая процедура представляет собой простую вставку в таблицу People, вы можете создать новую хранимую процедуру, например:

CREATE PROCEDURE dbo.Insert_People_From_XML
    @people_xml XML
AS
BEGIN
    INSERT INTO dbo.People
    (
        id,
        first_name,
        last_name,
        middle_initial
    )
    SELECT
        Node.value('Id[1]', 'Int'),
        Node.value('FirstName[1]', 'varchar(50)'),
        Node.value('LastName[1]', 'varchar(50)'),
        Node.value('MI[1]', 'char(1)')
    FROM
        @people_xml.nodes('/ArrayOfPeople/Person') TempXML (Node)

END

Если у вас есть бизнес-логика (или другая логика, которая вам не нужнадублировать), то вы можете повторно использовать хранимую процедуру вставки, как она есть.В этом случае вам придется перебирать узлы XML.Как бы я ни старался избегать курсоров, самое время использовать один из них:

DECLARE
    @id                INT,
    @first_name        VARCHAR(50),
    @last_name         VARCHAR(50),
    @middle_initial    CHAR(1)

DECLARE people_cursor CURSOR FOR
SELECT
    Node.value('Id[1]', 'Int'),
    Node.value('FirstName[1]', 'varchar(50)'),
    Node.value('LastName[1]', 'varchar(50)'),
    Node.value('MI[1]', 'char(1)')
FROM
    @people_xml.nodes('/ArrayOfPeople/Person') TempXML (Node)

OPEN people_cursor

FETCH NEXT FROM people_cursor INTO @id, @first_name, @last_name, @middle_initial

WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC Your_Proc
        @id = @id,
        @first_name = @first_name,
        @last_name = @last_name,
        @middle_initial = @middle_initial

    FETCH NEXT FROM people_cursor INTO @id, @first_name, @last_name, @middle_initial
END

CLOSE people_cursor

DEALLOCATE people_cursor

ПРИМЕЧАНИЕ: Все это было написано на моей голове.Я не очень часто использую XML, поэтому, возможно, потребуется исправить синтаксис, вы захотите добавить обработку ошибок и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...