Travis Laborde Blog

play boxing daddy?

Using XML To Send Multiple Rows At Once Into A Stored Procedure

From time to time, people ask the question "How can I insert many records at once into SQL Server?"  The purpose of this quick article is to describe that process in very basic details.  I'll give a very simple example, so that you can then take it from there.

 

I find that it's easiest to visualize if you start with a very simple XML document.  Here is an example XML snippet:

 

<items>

            <item id="1"></item>

            <item id="4"></item>

            <item id="12"></item>

            <item id="112"></item>

            <item id="234"></item>

            <item id="605"></item>

</items>

 

Let's say you have a checkboxlist, and you want to send the list of "checked" items into a SQL Server stored procedure, making an INSERT for each checked item.  You want to create a string containing text that is formatted as above, and for each checked item, insert a "row."  Here is a simple class in VB.NET to abstract that functionality:

 

Public Class XMLItemList

    Private sb As System.Text.StringBuilder

 

    Public Sub New()

        sb = New System.Text.StringBuilder

        sb.Append("<items>" & vbCrLf)

    End Sub

 

    Public Sub AddItem(ByVal Item As String)

        sb.AppendFormat("<item id={0}{1}{2}></item>{3}", Chr(34), Item, Chr(34), vbCrLf)

    End Sub

 

    Public Overrides Function ToString() As String

        sb.Append("</items>" & vbCrLf)

        Return sb.ToString

    End Function

 

End Class

 

As you can see, there is nothing special or fancy going on here.  The purpose of the class is just to make the next example easier to understand:

 

Dim MyXMLItemList As New XMLItemList

For i As Integer = 0 To MyCheckBoxList.Items.Count - 1

    If MyCheckBoxList.Items(i).Selected = True Then

        MyXMLItemList.AddItem(MyCheckBoxList.Items(i).Value)

    End If

Next

 

Given the above, you can use the MyXMLItemList.ToString method to get a string representation that is formatted like the XML snippet described in the beginning.

 

All that remains then is to call your stored procedure, passing in the string produced above as a parameter.  Here is how that stored procedure would be written:

 

alter procedure usp_InsertManyRows

@XMLDOC varchar(8000)

AS

 

declare @xml_hndl int

 

--prepare the XML Document by executing a system stored procedure

exec sp_xml_preparedocument @xml_hndl OUTPUT, @XMLDOC

 

 

--insert into table

Insert Into testtable

            (

            InsertedID

            )

Select

            IDToInsert

From

            OPENXML(@xml_hndl, '/items/item', 1)

            With

                        (

                        IDToInsert int '@id'

                        )

 

 

Now follows a comparison of how each performs.  The following tests were run with simple ASP.NET pages using a local SQL Server database.  The results are quite dramatic, and would only be more dramatic if the hits had to go over the network:

 

First, I created a simple page that hit the database 10 times, each time inserting one record.  Here are the results of that test:

            97 Requests Per Second

            28254 hits in 5 minutes

            282540 records inserted

           

Next, I created a simple page that hits the database only once, sending in all ten records to be inserted together at once, using the XML format mentioned in this article.  Here are the results of that test:

            186 Requests Per Second

            55349 hits in 5 minutes

            553490 records inserted

 

Quite an impressive difference!

 

Legacy Comments


Mike Swaim
2005-01-04
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
2 things

1) What's the performance of doing 10 inserts/request? (I believe that MS is looking into doing something like that with datasets, to speed up updates.)

2) If you're using Oracle, you can pass arrays to SQL statements. It's a cleaner and faster implementation of what you're doing above, especially with large amounts of data. (I was using 10,000 row arrays, doing inserts whenever they filled up.)

Travis Laborde
2005-01-04
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Mike, I'm not sure I understand your question. The two test scenarios that I ran were:

1) Where the web page actually hit the database 10 times, once for each record to be inserted. So, one "hit" of the webpage would cause 10 "hits" to the database, for 10 records to be added.

2) Where the web page only hit the database once, sending in the XML snippet as one parameter, which was then parsed by the stored procedure. So, one "hit" to the webpage would cause only one "hit" to the database, for 10 records to be added.

The performace differences were listed at the end of the article.

Mike Swaim
2005-01-04
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
One of the tricks to improve SQL Server performance is to concatenate multiple commands per round trip to the database. So issuing "insert into foo values(1);insert into foo values(2);insert into foo values(3)" is noticably more efficent than
"insert into foo values(1)", "insert into foo values(2)", "insert into foo values(3)".

I'm curious whether simply concatenating SQL commands is faster or slower than using XML and going through a stored procedure.

Travis Laborde
2005-01-05
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Mike - You are correct. I do have two small issues with that method though:

First, I'm sure that multiple inserts would not perform as well as the INSERT SELECT process. But, I'll test that, and get back to you...

Second, I have personally given up on dynamic SQL, in favor of stored procedures everywhere. It's certainly beyond my ability or desire to argue the case, but I'm sure that a quick search will find you many articles published, in the last year alone, on that topic. Though I know that there are "safe" ways to do it, in my experience it is very typical for an ASP developer to do dynamic SQL in a very bad way, susceptible to injection attacks, etc.


Todd - thanks for your comments as well. I agree Erland has a great article there. Obviously, much less was put into my article. I was not intending to show the BEST way to send an array of data into SQL Server, but rather to show ONE way, a very SIMPLE and easy to understand way, that can be expanded upon with a lot of flexibility.

It's not about the code, it's about the concept. People think "I've got this series of checked items and I want to send them all to the database at once." I think this was a very clear beginning tutorial on the OPENXML command in TSQL. I appreciate that you use a different method.

Mike Swaim
2005-01-16
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
I've decided that I don't like SPs for the following reasons.
1)For simple statements, it roughly doubles your code. (You still have the same amount of code on the client, and you now also have the SP code.)
2)For complicated one-off queries, I like to see the SQL with the code that's calling it. Also, if the query ever needs to change, you have to create a new SP, or risk breaking existing code.
3) I had a very bad experience once where a SP's signature changed, and it was missed in the client code. The bad thing was that it worked 99% of the time. Tracking it down was horrible.

Anyway, typically the only times than I need to build SQL is when I don't know what's going to be in my where clause until run time.
And I was shocked when I found out that people were having problems with SQL injection. Coming from PB/Delphi/C++, I assumed that everybody used parameterized SQL. Why don't ASPers?

vistor
2005-06-17
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
The greatest thing about string formatting in .net is reusability:

"<item id={0}{1}{2}></item>{3}", Chr(34), Item, Chr(34), vbCrLf

Could be:

"<item id={0}{1}{0}></item>{2}", Chr(34), Item, vbCrLf

The whole point of string formatting is to make the code easier to read... Good article.


Jude
2005-06-20
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Can you help me?

I am passing huge changed data (diffgram) of the dataset to ORACLE database in the format of XML. But when the size is exceeding the arround 2000 character the oracle is throwing a error

ORA-01460: unimplemented or unreasonable conversion requested SOURCE : System.Data.OracleClient

But i have declared the parameter type as CLOB.


Can you please help me out?


regards,
Jude

Jude
2005-06-20
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
<font color=blue>Can you help me?

I am passing huge volume of data - changed data (diffgram) of the dataset- to ORACLE Stored Procedure in the format of XML. But when the size is exceeding arround 2000 character, oracle is throwing an error

ORA-01460: unimplemented or unreasonable conversion requested SOURCE : System.Data.OracleClient

But i have declared the parameter type as CLOB.


Can you please help me out?


</font>

Ravi Gupta
2005-07-19
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Can you provide a sample Oracle stored procedure receiving XML as input and parsing the XML to do the insert.

Jude
2005-08-06
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi All,
I have done it. Now I am able to pass XML data upto 4GB on single trips.

Thanx to all of you.


rick
2005-09-01
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
How did you do it on the stored proc side? What param type are you using ? CLOB?

Affi
2005-09-15
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi All,
I have to insert Multiple rows of record in Multiple Tables can u help me on this.

Tej
2005-10-02
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi Jude!
I am also trying to pass in huge data in XML to an oracle stored procedure. While trying to do so I am getting the following error.

ORA-01460: unimplemented or unreasonable conversion requested

Can you please let me know how to resolve it?
Thanks in advance...
Tej

Tej
2005-10-03
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi all,

I am trying to pass in large data in XML from a VB component(vb 6.0) to an oracle stored procedure.With in the Oracle Stored procedure, I am parsing the data in XML and inserting the records into the database row by row. Pass in Parameter in VB method is of Type "adLongVarChar" and in Oracle SP the IN Parameter type is "Long".
When I tried with a small XML data samples, it is working fine. When I tried with a huge volume of XML data(1 MB) it is throwing the following error.

ORA-01460: unimplemented or unreasonable conversion requested

Can any body help me in resolving this problem?

Judy! I am very curious, you were able to pass XML data upto 4GB on single trips. It will be great if you let me know how did you do this.

Thanks to all of you.

Tej

Pic
2005-10-24
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Jude,

We are running into a similar problem trying to pass large XML into Oracle procs but run into the 32k limit on stored proc parameters. I'd love to know how you got a proc to take 4gb.

Pic

Suj
2005-11-06
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Can you please give the code in C# ?

Suj
2005-11-06
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
What is the equivalent of Chr(34), Item, Chr(34), vbCrLf in C#? Can any one reply please.

Chris
2006-02-03
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
I am having the same problem with Oracle. Did anybody get a response on how to do this?

Nishant
2006-02-07
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi,I amde the General SP for Bulk insert with the help of Dynamic SQl but i am getting an error that error in converting varchar daatatype to type of int.When i did Cast and Convert it removes the error but openXML first parameter require int datatye which is now changed to varchar so m getting an another error.i am unable to understande what shoul i do

Suraj
2006-03-23
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Can anyone give idea how who were able to pass 4gb of data to oracle DB through XML/clob.

Thanks

zap
2006-04-23
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi Iam getting problem while passing xmldata to
Stored procudure i dont know whats going on . Data not inserted into the table
My Sql Stored procedure is
CREATE procedure dbo.AddressMastAdd(@xmlDoc varchar(8000)) as
DECLARE @hDoc int,
@NSEndPos int,
@err int

EXEC @err = sp_xml_preparedocument @hdoc OUTPUT, @xmlDoc
SELECT @err = @@error + coalesce(@err, 4711)
IF @err <> 0 RETURN @err
insert into AddressMast(Classid,Formid,Addid,add1,city,zip,countryid)
select *
from openxml (@hdoc, 'NewDataSet/Tabel1',1)
with (Classid int '@classid',
Formid int '@Formid',
Addid int '@addid',
add1 nvarchar(50)'@add1',
city nvarchar(25)'@city',
zip char(10) '@zip',
countryid int '@countryid' )
EXEC sp_xml_removedocument @hdoc

and my xml file is

<NewDataSet>\r\n <Table1>\r\n <CLASSID>1</CLASSID>\r\n <FORMID>58</FORMID>\r\n <ADDID>1</ADDID>\r\n <ADD1>address1</ADD1>\r\n <CITY />\r\n <ZIP />\r\n <COUNTRYID>1</COUNTRYID>\r\n </Table1>\r\n</NewDataSet>

JUDE
2006-06-11
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi All,
I am sorry. I am here after a long time. If you are facing the same problem still then please post your request and also send a mail to judestephen@buildersv2b.com


regards,
Jude

Vaishali Shah
2006-06-14
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
I need to pass similar XML input to stored procedure. You wrote that you were able to do it. How did you manage 4GB? I am trying to call this proc from my j2EE app.

Thank you

kumar
2006-06-19
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Hi

this article is good and it is showing how v can imporve the application performance.

AA
2006-07-06
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Tej,
Could u please share the stored procedure code for bulk update to oracle datatable using XML.
It is very urgent. please do help.
Thanks in advance.

Rizzo
2006-07-10
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
SET NOCOUNT ON
INSERT tbl (someID, [somevalue]) VALUES (2,72);
INSERT tbl (someID, [somevalue]) VALUES (22,71);
INSERT tbl (someID, [somevalue]) VALUES (212,75);
INSERT tbl (someID, [somevalue]) VALUES (223,72);
...
etc..
GO

and got very-very-very fast Insert of rows....

Just parse it using StringBuilder, loop the data as much as you want up to the limit. Use Threading background while processing if you don't want to feel the neck, cast it into string then inject the sql statement. Done!

Trust me.... simple and very fast. Even the adapter.Update() cannot beat the sql string statement speed.

If you think of inserting millions of data... what??? use clustering of 4 SQL Server/Oracle, make it 10 Server if want more faster, split the INSERT statement into 4 or 10 parts... than you get the speed right. If not, don't bother to wait. hmmm... I wonder how long does the insert statement will last.


Kaiser
2006-08-02
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Jude I have sent you an email to check same issue

iris
2006-09-26
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
I also have a problem with passing a large xml clob to my store procedure
if anyone solved this issue please email me
at iris.abramovitz@mullintbg.com
Thanks

prakash patil
2006-12-07
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure 8/6/2005 2:55 AM Jude
I need to pass XML file as input to stored procedure. You wrote that you were able to do it. How did you manage 4GB? plz mail me

Anil Kumar
2007-01-11
re: Using XML To Send Multiple Rows At Once Into A Stored Procedure
Perhaps, This is the best article i have ever seen on the net about sending multiple parameters as xml to Stored Procedure.
Can any one of you guys publish the code of the
Application, StoredProc to demonstrate this on Northwind DB?
Say, i have 5 rows in DataTable.i want to send all 5 rows once to the sp.how can i do that.