Question : OpenXML and inserting multiple rows (in multiple tables) with identity

Hello Experts!

Here is my problem (i use examples!!!):

i have an quite simple XML file which looks like this:

--------------------------------

 

    Test
   
       foo
       bar
   

 

 

    Yak
   
       123
       foobar
       next
   

 


--------------------------------

the number of article and/or keyword items may vary.


now i have two tables:
One to store the "Articles":

Articles
------------
ident int IDENTITY(1,1),
name varchar(10)


One to store the "Keywords":

Keywords
------------
ident,
keyword varchar(10)


I can use the OpenXML function to populate the articles table, like this:

--------------------------------
insert into Articles
select      *
from    OpenXML(@hDoc, 'data/article')
with (
      name varchar(10) 'name'
)
--------------------------------


there is no problem inl getting the both articles into the table:

ident    name
----------------
1         Test
2         Yak


But now i want to assign the keywords to the articles using the auto-generated identity number (column: ident)!
Please note, that the name element is not always unique.

The keywords table should look like this:

ident    keyword
----------------
1         foo
1         bar
2         123
2         foobar
2         next



I am looking for any method to get those results WITHOUT using a cursor.

Answer : OpenXML and inserting multiple rows (in multiple tables) with identity

First of all thanks, It's the first time I use these meta tags
Here's new code to addresse problem 1)
--new view
create view v_article_keywords as select 0 as id, name, keyword
from articles a
inner join keywords k on a.ident = k.ident

--new trigger
create trigger tg_v_article_keywords on v_article_keywords
instead of insert as
declare c1 cursor for select distinct id, name from inserted
declare @name varchar(10), @id int
open C1
fetch c1 into @id, @name
while @@fetch_status = 0
begin
      insert Articles(name) values(@name)
      insert Keywords(ident, keyword) select scope_identity(), keyword from inserted where id = @id
      fetch c1 into @id, @name
end
close c1
deallocate c1

--new insert-select statement
declare @xml varchar(8000), @hdoc int
set @xml = '
 

    Test
   
       foo
       bar
   

 

 

    Yak
   
       123
       foobar
       next
   

 

'
exec sp_xml_preparedocument  @hdoc out, @xml
insert v_article_keywords (id, name, keyword)
select id, name, keyword
from openxml(@hdoc,'/data/article/keywords/keyword',1)
with (id int '@mp:parentid', name varchar(10) '../../name', keyword varchar(10) 'text()')
exec sp_xml_removedocument @hdoc

As for problem 2), I try to never use cursors and most of the time they can be avoided.
In this case I can't think of any way to get rid of the cursor (except another kind of loop that won't be better performancewise)

>>Are there any known disadvantages using the method above?<<
It somehow hides the complexity in the trigger and I tend to think the performance should not be too bad, cause it keeps things simple both in the trigger and in the insert-select code.

I must admit it's somehow unusual ... in fact I have seldom seen cases where INSTEAD OF triggers were used with real added value.
I hope the code above is a good exemple ...

Cheers

Hilaire
Random Solutions  
 
programming4us programming4us