Click here to Skip to main content
15,888,351 members
Articles / Database Development / SQL Server
Article

A generic bulk insert using DataSets and OpenXML

Rate me:
Please Sign up or sign in to vote.
4.29/5 (14 votes)
14 Apr 20053 min read 247.3K   67   34
Create T-SQL command text to update a table with OpenXML quickly and with minimal effort.

Introduction

The project I’m working on now requires a way to drop a significant amount of data into 20+ tables. I went looking for Bulk Insert solutions and what I found was these articles in the MSDN.

The article explains how to prepare a table as XML using its DataSet’s schema, then sending it to a stored procedure to execute an Update and Insert. The problem I saw for my needs was that the MSDN solution requires a function and a stored procedure for each table.

So I spent a day and rolled out this code here. It takes a DataSet, an open SQL connection and a table name and writes the command text to execute an OPENXML Bulk Insert.

The Code

There is one calling function and two support functions. The first function takes three parameters:

  • a DataSet,
  • an open SQL connection,
  • and a table name.

and begins by processing the table’s ColumnMapping, just like MSDN’s tutorial. It also streams the DataSet to a StringBuilder as XML. Then, instead of sending the XML to a stored procedure, it sends it to buildBulkUpdateSql which creates the remaining T-SQL script.

C#
/// <summary>
/// Takes a dataset and creates a OPENXML script dynamically around it for 
/// bulk inserts 
/// </summary> 
/// <remarks>The DataSet must have at least one primary key, otherwise it'll wipe 
/// out the entire table, then insert the dataset. Multiple Primary Keys are okay. 
/// The dataset's columns must match the target table's columns EXACTLY. A 
/// dataset column "democd" does not work for the sql column
/// "DemoCD". Any missing or incorrect data is assumed NULL (default).
/// </remarks>
/// <param name="objDS">Dataset containing target DataTable.</PARAM>
/// <param name="objCon">Open Connection to the database.</PARAM>
/// <param name="tablename">Name of table to save.</PARAM>
public static void BulkTableInsert(DataSet objDS, 
                                 SqlConnection objCon, string tablename)
{
    //Change the column mapping first.
    System.Text.StringBuilder sb = new System.Text.StringBuilder( 1000);
    System.IO.StringWriter sw = new System.IO.StringWriter(sb); 
    foreach( DataColumn col in objDS.Tables[tablename].Columns)
    {
         col.ColumnMapping = System.Data.MappingType.Attribute;
    }
    objDS.WriteXml(sw, System.Data.XmlWriteMode.WriteSchema);
    string sqlText = buildBulkUpdateSql(sb.ToString(), objDS.Tables[tablename]);
    execSql(objCon, sqlText);
}

This is where the generic T-SQL text is created. The only magic here is getting the C# escape characters out of the string before sending it to the SqlCommand. Another thing to note is how I’m using the database’s table as the schema to work within the WITH argument so that I don’t have to name each column and DataType.

C#
static string buildBulkUpdateSql( string dataXml, DataTable table)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    dataXml = dataXml.Replace(Environment.NewLine, "");
    dataXml = dataXml.Replace("\"", "''");
    //init the xml doc
    sb.Append(" SET NOCOUNT ON");
    sb.Append(" DECLARE @hDoc INT");
    sb.AppendFormat(" EXEC sp_xml_preparedocument @hDoc OUTPUT, '{0}'", dataXml);
    //This code deletes old data based on PK.
    sb.AppendFormat(" DELETE {0} FROM {0} INNER JOIN ", table.TableName);
    sb.AppendFormat(" (SELECT * FROM OPENXML (@hdoc, '/NewDataSet/{0}', 1)", 
    table.TableName);
    sb.AppendFormat(" WITH {0}) xmltable ON 1 = 1", table.TableName);
    foreach( DataColumn col in table.PrimaryKey)
    {
        sb.AppendFormat(" AND {0}.{1} = xmltable.{1}", table.TableName, 
        col.ColumnName);
    }
    //This code inserts new data.
    sb.AppendFormat(" INSERT INTO {0} SELECT *", table.TableName);
    sb.AppendFormat(" FROM OPENXML (@hdoc, '/NewDataSet/{0}', 1) WITH {0}", 
    table.TableName);
    //clear the xml doc
    sb.Append(" EXEC sp_xml_removedocument @hDoc");
    return sb.ToString(); 
}

There’s no magic here. This is just a simple command executer. In my actual app I don’t use this and I don’t expect you to use this as well, but for code-completion, here it is:

C#
static void execSql(SqlConnection objCon, string sqlText)
{
    SqlCommand objCom = new SqlCommand();
    objCom.Connection = objCon;
    objCom.CommandType = CommandType.Text;
    objCom.CommandText = sqlText;
    objCom.ExecuteNonQuery();
}

Drawbacks

As the documentation in the function header says, this procedure assumes a few things:

  • The DataTable must have at least one primary key so that it knows what is update data and what is not.
  • The existing data matched by the primary key will be deleted, and then re-inserted. This can be debated as to whether it is a good idea or not. I believe it would speed up the transaction as a whole, but perhaps it is not the most elegant solution. I’m interested in any DBA comments. Doing the update part is easy, but then you would have to do an outer join against the XML table for the Insert data; which could take a while depending on the table size.
  • The DataTable column names must match the database’s table perfectly. This is kind of a bummer, but if you’re auto-magically creating DataSets in the IDE, it shouldn’t matter to you.

TODO

Rip out unnecessary XML before creating the Insert script. DataSets can contain multiple tables, all of which are written out with the DataSet.WriteXml() function. In large samples, this is too much data to be send across and is completely useless.

Conclusion

I’ve tested the heck out of this using small and medium size tables and DataSets. There is tons of room for improvement and feature enhancement and I know this won’t work in many professional environments, but it’s a good start for me that I wish I had two days ago. Like I mentioned, I'm looking forward to hearing from the community about speeding up this snippet a bit.

Links

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
writing for the financial and television industries since 1997. Currently working for Transformational Security in Baltimore, Maryland as Architect.

Comments and Discussions

 
GeneralJunk. Use SqlBulkCopy instead. Pin
llitsanylg28-Aug-09 0:38
llitsanylg28-Aug-09 0:38 
GeneralRe: Junk. Use SqlBulkCopy instead. Pin
poodull7628-Aug-09 3:49
poodull7628-Aug-09 3:49 
GeneralRe: Junk. Use SqlBulkCopy instead. Pin
dmofo26-Jun-12 7:03
dmofo26-Jun-12 7:03 
GeneralProblem with OPENXML ?, Bulk Insert ?, Encoding ? [modified] Pin
Xavito23-Apr-09 17:30
Xavito23-Apr-09 17:30 
I’ve been working on a procedure in order to insert data from a Web Service to a SQL Server using a Bulk Insert.
Something like this:

Line1 DataSet dsAd_Mstr = objWebServices.Obtener_Ad_Mstr();
Line2 objConnectionC.Open();
Line3 Global.BulkTableInsert(dsAd_Mstr, objConnectionC, "Ad_Mstr");

In the first line I’m extracting the information from a Web Service. The web method looks like this:

Line4 [WebMethod]
Line5 public DataSet Obtener_Ad_Mstr()
Line6 {
Line7 COffline oOffline = new COffline();

Line8 try
Line9 {
Line10 return oOffline.Obtener_Ad_Mstr();
Line11 }
Line12 catch (Exception ex)
Line13 {
Line14 throw(ex);
Line15 }
Line16 finally
Line17 {
Line18 oOffline = null;
Line19 }
Line20 }

This will return something like this:

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="ad_mstr">
<xs:complexType>
<xs:sequence>
<xs:element name="ad_addr" type="xs:string" minOccurs="0" />
<xs:element name="ad_name" type="xs:string" minOccurs="0" />
<xs:element name="ad_line1" type="xs:string" minOccurs="0" />
<xs:element name="ad_line2" type="xs:string" minOccurs="0" />
<xs:element name="ad_city" type="xs:string" minOccurs="0" />
<xs:element name="ad_state" type="xs:string" minOccurs="0" />
<xs:element name="ad_zip" type="xs:string" minOccurs="0" />
<xs:element name="ad_type" type="xs:string" minOccurs="0" />
<xs:element name="ad_attn" type="xs:string" minOccurs="0" />
<xs:element name="ad_phone" type="xs:string" minOccurs="0" />
<xs:element name="ad_ext" type="xs:string" minOccurs="0" />
<xs:element name="ad_ref" type="xs:string" minOccurs="0" />
<xs:element name="ad_sort" type="xs:string" minOccurs="0" />
<xs:element name="ad_country" type="xs:string" minOccurs="0" />
<xs:element name="ad_attn2" type="xs:string" minOccurs="0" />
<xs:element name="ad_phone2" type="xs:string" minOccurs="0" />
<xs:element name="ad_ext2" type="xs:string" minOccurs="0" />
<xs:element name="ad_fax" type="xs:string" minOccurs="0" />
<xs:element name="ad_fax2" type="xs:string" minOccurs="0" />
<xs:element name="ad_line3" type="xs:string" minOccurs="0" />
<xs:element name="ad_user1" type="xs:string" minOccurs="0" />
<xs:element name="ad_user2" type="xs:string" minOccurs="0" />
<xs:element name="ad_lang" type="xs:string" minOccurs="0" />
<xs:element name="ad_pst_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_date" type="xs:string" minOccurs="0" />
<xs:element name="ad_county" type="xs:string" minOccurs="0" />
<xs:element name="ad_temp" type="xs:boolean" minOccurs="0" />
<xs:element name="ad_bk_acct1" type="xs:string" minOccurs="0" />
<xs:element name="ad_bk_acct2" type="xs:string" minOccurs="0" />
<xs:element name="ad_format" type="xs:int" minOccurs="0" />
<xs:element name="ad_vat_reg" type="xs:string" minOccurs="0" />
<xs:element name="ad_coc_reg" type="xs:string" minOccurs="0" />
<xs:element name="ad_gst_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_tax_type" type="xs:string" minOccurs="0" />
<xs:element name="ad_taxc" type="xs:string" minOccurs="0" />
<xs:element name="ad_taxable" type="xs:boolean" minOccurs="0" />
<xs:element name="ad_tax_in" type="xs:boolean" minOccurs="0" />
<xs:element name="ad_conrep" type="xs:string" minOccurs="0" />
<xs:element name="ad_edi_tpid" type="xs:string" minOccurs="0" />
<xs:element name="ad_edi_ctrl" type="xs:string" minOccurs="0" />
<xs:element name="ad_timezone" type="xs:string" minOccurs="0" />
<xs:element name="ad_userid" type="xs:string" minOccurs="0" />
<xs:element name="ad_mod_date" type="xs:string" minOccurs="0" />
<xs:element name="ad_edi_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_barlbl_prt" type="xs:string" minOccurs="0" />
<xs:element name="ad_barlbl_val" type="xs:string" minOccurs="0" />
<xs:element name="ad_calendar" type="xs:string" minOccurs="0" />
<xs:element name="ad_edi_std" type="xs:string" minOccurs="0" />
<xs:element name="ad_edi_level" type="xs:string" minOccurs="0" />
<xs:element name="ad__qad01" type="xs:string" minOccurs="0" />
<xs:element name="ad__qad02" type="xs:string" minOccurs="0" />
<xs:element name="ad__qad03" type="xs:string" minOccurs="0" />
<xs:element name="ad__qad04" type="xs:string" minOccurs="0" />
<xs:element name="ad__qad05" type="xs:string" minOccurs="0" />
<xs:element name="ad__chr01" type="xs:string" minOccurs="0" />
<xs:element name="ad__chr02" type="xs:string" minOccurs="0" />
<xs:element name="ad__chr03" type="xs:string" minOccurs="0" />
<xs:element name="ad__chr04" type="xs:string" minOccurs="0" />
<xs:element name="ad__chr05" type="xs:string" minOccurs="0" />
<xs:element name="ad_tp_loc_code" type="xs:string" minOccurs="0" />
<xs:element name="ad_ctry" type="xs:string" minOccurs="0" />
<xs:element name="ad_tax_zone" type="xs:string" minOccurs="0" />
<xs:element name="ad_tax_usage" type="xs:string" minOccurs="0" />
<xs:element name="ad_misc1_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_misc2_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_misc3_id" type="xs:string" minOccurs="0" />
<xs:element name="ad_wk_offset" type="xs:int" minOccurs="0" />
<xs:element name="ad_inv_mthd" type="xs:string" minOccurs="0" />
<xs:element name="ad_sch_mthd" type="xs:string" minOccurs="0" />
<xs:element name="ad_po_mthd" type="xs:string" minOccurs="0" />
<xs:element name="ad_asn_data" type="xs:string" minOccurs="0" />
<xs:element name="ad_intr_division" type="xs:string" minOccurs="0" />
<xs:element name="ad_tax_report" type="xs:boolean" minOccurs="0" />
<xs:element name="ad_name_control" type="xs:string" minOccurs="0" />
<xs:element name="ad_last_file" type="xs:boolean" minOccurs="0" />
<xs:element name="ad_domain" type="xs:string" minOccurs="0" />
<xs:element name="oid_ad_mstr" type="xs:decimal" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<ad_mstr diffgr:id="ad_mstr4073" msdata:rowOrder="4072">
<ad_addr>SOCIOS3</ad_addr>
<ad_name>COMPANY X</ad_name>
<ad_line1 />
<ad_line2 />
<ad_city />
<ad_state />
<ad_zip />
<ad_type>customer</ad_type>
<ad_attn />
<ad_phone />
<ad_ext />
<ad_ref />
<ad_sort>COMPANY X</ad_sort>
<ad_country>MEXICO</ad_country>
<ad_attn2 />
<ad_phone2 />
<ad_ext2 />
<ad_fax />
<ad_fax2 />
<ad_line3 />
<ad_user1 />
<ad_user2 />
<ad_lang />
<ad_pst_id />
<ad_date>02/03/1993</ad_date>
<ad_county />
<ad_temp>false</ad_temp>
<ad_bk_acct1 />
<ad_bk_acct2 />
<ad_format>0</ad_format>
<ad_vat_reg />
<ad_coc_reg />
<ad_gst_id />
<ad_tax_type />
<ad_taxc>1</ad_taxc>
<ad_taxable>true</ad_taxable>
<ad_tax_in>false</ad_tax_in>
<ad_conrep />
<ad_edi_tpid />
<ad_edi_ctrl>;;;;</ad_edi_ctrl>
<ad_timezone />
<ad_userid />
<ad_edi_id />
<ad_barlbl_prt />
<ad_barlbl_val />
<ad_calendar />
<ad_edi_std />
<ad_edi_level />
<ad__qad01 />
<ad__qad02 />
<ad__qad03 />
<ad__qad04 />
<ad__qad05 />
<ad__chr01 />
<ad__chr02 />
<ad__chr03 />
<ad__chr04 />
<ad__chr05 />
<ad_tp_loc_code />
<ad_ctry>MEX</ad_ctry>
<ad_tax_zone>MEXICO</ad_tax_zone>
<ad_tax_usage>BUSES</ad_tax_usage>
<ad_misc1_id />
<ad_misc2_id />
<ad_misc3_id />
<ad_wk_offset>0</ad_wk_offset>
<ad_inv_mthd />
<ad_sch_mthd />
<ad_po_mthd />
<ad_asn_data />
<ad_intr_division />
<ad_tax_report>false</ad_tax_report>
<ad_name_control />
<ad_last_file>false</ad_last_file>
<ad_domain>VIM</ad_domain>
<oid_ad_mstr>0</oid_ad_mstr>
</ad_mstr>
.
.
<ad_mstr diffgr:id="ad_mstr4074" msdata:rowOrder="4073">
<ad_addr>SOCIOS4</ad_addr>
<ad_name>COMPANY Y</ad_name>
<ad_line1 />
<ad_line2 />
<ad_city />
<ad_state />
<ad_zip />
<ad_type>customer</ad_type>
<ad_attn />
<ad_phone />
<ad_ext />
<ad_ref />
<ad_sort>COMPANY Y</ad_sort>
<ad_country>MEXICO</ad_country>
<ad_attn2 />
<ad_phone2 />
<ad_ext2 />
<ad_fax />
<ad_fax2 />
<ad_line3 />
<ad_user1 />
<ad_user2 />
<ad_lang />
<ad_pst_id />
<ad_date>02/03/1993</ad_date>
<ad_county />
<ad_temp>false</ad_temp>
<ad_bk_acct1 />
<ad_bk_acct2 />
<ad_format>0</ad_format>
<ad_vat_reg />
<ad_coc_reg />
<ad_gst_id />
<ad_tax_type />
<ad_taxc>1</ad_taxc>
<ad_taxable>true</ad_taxable>
<ad_tax_in>false</ad_tax_in>
<ad_conrep />
<ad_edi_tpid />
<ad_edi_ctrl>;;;;</ad_edi_ctrl>
<ad_timezone />
<ad_userid />
<ad_edi_id />
<ad_barlbl_prt />
<ad_barlbl_val />
<ad_calendar />
<ad_edi_std />
<ad_edi_level />
<ad__qad01 />
<ad__qad02 />
<ad__qad03 />
<ad__qad04 />
<ad__qad05 />
<ad__chr01 />
<ad__chr02 />
<ad__chr03 />
<ad__chr04 />
<ad__chr05 />
<ad_tp_loc_code />
<ad_ctry>MEX</ad_ctry>
<ad_tax_zone>MEXICO</ad_tax_zone>
<ad_tax_usage>BUSES</ad_tax_usage>
<ad_misc1_id />
<ad_misc2_id />
<ad_misc3_id />
<ad_wk_offset>0</ad_wk_offset>
<ad_inv_mthd />
<ad_sch_mthd />
<ad_po_mthd />
<ad_asn_data />
<ad_intr_division />
<ad_tax_report>false</ad_tax_report>
<ad_name_control />
<ad_last_file>false</ad_last_file>
<ad_domain>VIM</ad_domain>
<oid_ad_mstr>0</oid_ad_mstr>
</ad_mstr>
</NewDataSet>
</diffgr:diffgram>
</DataSet>

I think there is no need to explain line number 2.

The line number 3 is a calling to the following function:

Line21 public static void BulkTableInsert(DataSet objDS, SqlConnection objCon, string tablename)
Line22 {
Line23 //Change the column mapping first.
Line24 System.Text.StringBuilder sb = new System.Text.StringBuilder( 1000);
Line25 System.IO.StringWriter sw = new System.IO.StringWriter(sb);
Line26 foreach( DataColumn col in objDS.Tables[tablename].Columns)
Line27 {
Line28 col.ColumnMapping = System.Data.MappingType.Attribute;
Line29 }
Line30
Line31 objDS.WriteXml(sw, System.Data.XmlWriteMode.WriteSchema);
Line32 string sqlText = buildBulkUpdateSql(sb.ToString(), objDS.Tables[tablename]);
Line33

Line34 sqlText = sqlText.Replace("''true''", "''1''");
Line35 sqlText = sqlText.Replace("''false''", "''0''");
Line36 sqlText = sqlText.Replace("á", "a");
Line37 sqlText = sqlText.Replace("é", "e");
Line38 sqlText = sqlText.Replace("í", "i");
Line39 sqlText = sqlText.Replace("ó", "o");
Line40 sqlText = sqlText.Replace("ú", "u");
Line41 sqlText = sqlText.Replace("Ñ", "N");
Line42 sqlText = sqlText.Replace("ñ", "n");

Line43 execSql(objCon, sqlText);
Line44 }

The line 32 is calling the following function:

Line45 static string buildBulkUpdateSql( string dataXml, DataTable table)
Line46 {
Line47 System.Text.StringBuilder sb = new System.Text.StringBuilder();
Line48 dataXml = dataXml.Replace(Environment.NewLine, "");
Line49 dataXml = dataXml.Replace("\"", "''");
Line50 //init the xml doc
Line51 sb.Append(" SET NOCOUNT ON");
Line52 sb.Append(" DECLARE @hDoc INT");
Line53 //sb.AppendFormat(" EXEC sp_xml_preparedocument @hDoc OUTPUT, '<?xml version=''1.0'' encoding=''iso-8859-1''?> {0}'", dataXml);
Line54 sb.AppendFormat(" EXEC sp_xml_preparedocument @hDoc OUTPUT, '{0}'", dataXml);
Line55 //This code deletes old data based on PK.
Line56 sb.AppendFormat(" DELETE {0} FROM {0} INNER JOIN ", table.TableName);
Line57 sb.AppendFormat(" (SELECT * FROM OPENXML (@hdoc, '/NewDataSet/{0}', 1)",
Line58 table.TableName);
Line59 sb.AppendFormat(" WITH {0}) xmltable ON 1 = 1", table.TableName);
Line60 foreach( DataColumn col in table.PrimaryKey)
Line61 {
Line62 sb.AppendFormat(" AND {0}.{1} = xmltable.{1}", table.TableName,
Line63 col.ColumnName);
Line64 }
Line65 //This code inserts new data.
Line66 sb.AppendFormat(" INSERT INTO {0} SELECT *", table.TableName);
Line67 sb.AppendFormat(" FROM OPENXML (@hdoc, '/NewDataSet/{0}', 1) WITH {0}",
Line68 table.TableName);
Line69 //clear the xml doc
Line70 sb.Append(" EXEC sp_xml_removedocument @hDoc");
Line71 return sb.ToString();
Line72 }

I think that you can imagine what does the function called in line 43 but I’m adding it below:

Line73 static void execSql(SqlConnection objCon, string sqlText)
Line74 {
Line75 SqlCommand objCom = new SqlCommand();
Line76 objCom.Connection = objCon;
Line77 objCom.CommandType = CommandType.Text;
Line78 objCom.CommandText = sqlText;
Line79 objCom.ExecuteNonQuery();
Line80 }

I’m taking these 3 last function from the article A generic bulk insert using DataSets and OpenXML from CodeProject (http://www.codeproject.com/KB/database/generic_OpenXml.aspx?fid=171911&df=90&mpp=25&noise=3&sort=Position&view=Quick).

So far the whole procedure looks great.

But when I execute the calling to the line 3, an exception throws stating just an SQL Exception.

The code generated (sqlText) by the BulkTableInsert looks like this:

SET NOCOUNT ON DECLARE @hDoc INT EXEC sp_xml_preparedocument @hDoc OUTPUT,
'<NewDataSet> <xs:schema id=''NewDataSet'' xmlns='''' xmlns:xs=''http://www.w3.org/2001/XMLSchema'' xmlns:msdata=''urn:schemas-microsoft-com:xml-msdata''> <xs:element name=''NewDataSet'' msdata:IsDataSet=''1''> <xs:complexType> <xs:choice maxOccurs=''unbounded''> <xs:element name=''ad_mstr''> <xs:complexType> <xs:attribute name=''ad_addr'' type=''xs:string'' /> <xs:attribute name=''ad_name'' type=''xs:string'' /> <xs:attribute name=''ad_line1'' type=''xs:string'' /> <xs:attribute name=''ad_line2'' type=''xs:string'' /> <xs:attribute name=''ad_city'' type=''xs:string'' /> <xs:attribute name=''ad_state'' type=''xs:string'' /> <xs:attribute name=''ad_zip'' type=''xs:string'' /> <xs:attribute name=''ad_type'' type=''xs:string'' /> <xs:attribute name=''ad_attn'' type=''xs:string'' /> <xs:attribute name=''ad_phone'' type=''xs:string'' /> <xs:attribute name=''ad_ext'' type=''xs:string'' /> <xs:attribute name=''ad_ref'' type=''xs:string'' /> <xs:attribute name=''ad_sort'' type=''xs:string'' /> <xs:attribute name=''ad_country'' type=''xs:string'' /> <xs:attribute name=''ad_attn2'' type=''xs:string'' /> <xs:attribute name=''ad_phone2'' type=''xs:string'' /> <xs:attribute name=''ad_ext2'' type=''xs:string'' /> <xs:attribute name=''ad_fax'' type=''xs:string'' /> <xs:attribute name=''ad_fax2'' type=''xs:string'' /> <xs:attribute name=''ad_line3'' type=''xs:string'' /> <xs:attribute name=''ad_user1'' type=''xs:string'' /> <xs:attribute name=''ad_user2'' type=''xs:string'' /> <xs:attribute name=''ad_lang'' type=''xs:string'' /> <xs:attribute name=''ad_pst_id'' type=''xs:string'' /> <xs:attribute name=''ad_date'' type=''xs:string'' /> <xs:attribute name=''ad_county'' type=''xs:string'' /> <xs:attribute name=''ad_temp'' type=''xs:boolean'' /> <xs:attribute name=''ad_bk_acct1'' type=''xs:string'' /> <xs:attribute name=''ad_bk_acct2'' type=''xs:string'' /> <xs:attribute name=''ad_format'' type=''xs:int'' /> <xs:attribute name=''ad_vat_reg'' type=''xs:string'' /> <xs:attribute name=''ad_coc_reg'' type=''xs:string'' /> <xs:attribute name=''ad_gst_id'' type=''xs:string'' /> <xs:attribute name=''ad_tax_type'' type=''xs:string'' /> <xs:attribute name=''ad_taxc'' type=''xs:string'' /> <xs:attribute name=''ad_taxable'' type=''xs:boolean'' /> <xs:attribute name=''ad_tax_in'' type=''xs:boolean'' /> <xs:attribute name=''ad_conrep'' type=''xs:string'' /> <xs:attribute name=''ad_edi_tpid'' type=''xs:string'' /> <xs:attribute name=''ad_edi_ctrl'' type=''xs:string'' /> <xs:attribute name=''ad_timezone'' type=''xs:string'' /> <xs:attribute name=''ad_userid'' type=''xs:string'' /> <xs:attribute name=''ad_mod_date'' type=''xs:string'' /> <xs:attribute name=''ad_edi_id'' type=''xs:string'' /> <xs:attribute name=''ad_barlbl_prt'' type=''xs:string'' /> <xs:attribute name=''ad_barlbl_val'' type=''xs:string'' /> <xs:attribute name=''ad_calendar'' type=''xs:string'' /> <xs:attribute name=''ad_edi_std'' type=''xs:string'' /> <xs:attribute name=''ad_edi_level'' type=''xs:string'' /> <xs:attribute name=''ad__qad01'' type=''xs:string'' /> <xs:attribute name=''ad__qad02'' type=''xs:string'' /> <xs:attribute name=''ad__qad03'' type=''xs:string'' /> <xs:attribute name=''ad__qad04'' type=''xs:string'' /> <xs:attribute name=''ad__qad05'' type=''xs:string'' /> <xs:attribute name=''ad__chr01'' type=''xs:string'' /> <xs:attribute name=''ad__chr02'' type=''xs:string'' /> <xs:attribute name=''ad__chr03'' type=''xs:string'' /> <xs:attribute name=''ad__chr04'' type=''xs:string'' /> <xs:attribute name=''ad__chr05'' type=''xs:string'' /> <xs:attribute name=''ad_tp_loc_code'' type=''xs:string'' /> <xs:attribute name=''ad_ctry'' type=''xs:string'' /> <xs:attribute name=''ad_tax_zone'' type=''xs:string'' /> <xs:attribute name=''ad_tax_usage'' type=''xs:string'' /> <xs:attribute name=''ad_misc1_id'' type=''xs:string'' /> <xs:attribute name=''ad_misc2_id'' type=''xs:string'' /> <xs:attribute name=''ad_misc3_id'' type=''xs:string'' /> <xs:attribute name=''ad_wk_offset'' type=''xs:int'' /> <xs:attribute name=''ad_inv_mthd'' type=''xs:string'' /> <xs:attribute name=''ad_sch_mthd'' type=''xs:string'' /> <xs:attribute name=''ad_po_mthd'' type=''xs:string'' /> <xs:attribute name=''ad_asn_data'' type=''xs:string'' /> <xs:attribute name=''ad_intr_division'' type=''xs:string'' /> <xs:attribute name=''ad_tax_report'' type=''xs:boolean'' /> <xs:attribute name=''ad_name_control'' type=''xs:string'' /> <xs:attribute name=''ad_last_file'' type=''xs:boolean'' /> <xs:attribute name=''ad_domain'' type=''xs:string'' /> <xs:attribute name=''oid_ad_mstr'' type=''xs:decimal'' /> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema>
<ad_mstr ad_addr=''SOCIOS3'' ad_name=''COMPANY X'' ad_line1='''' ad_line2='''' ad_city='''' ad_state='''' ad_z
ip='''' ad_type=''customer'' ad_attn='''' ad_phone='''' ad_ext='''' ad_ref='''' ad_sort=''COMPANY X'' ad_country=''MEXICO'' ad_attn2='''' ad_phone2='''' ad_ext2='''' ad_fax='''' ad_fax2='''' ad_line3='''' ad_user1='''' ad_user2='''' ad_lang='''' ad_pst_id='''' ad_date=''02/03/1993'' ad_county='''' ad_temp=''0'' ad_bk_acct1='''' ad_bk_acct2='''' ad_format=''0'' ad_vat_reg='''' ad_coc_reg='''' ad_gst_id='''' ad_tax_type='''' ad_taxc=''1'' ad_taxable=''1'' ad_tax_in=''0'' ad_conrep='''' ad_edi_tpid='''' ad_edi_ctrl='';;;;'' ad_timezone='''' ad_userid='''' ad_edi_id='''' ad_barlbl_prt='''' ad_barlbl_val='''' ad_calendar='''' ad_edi_std='''' ad_edi_level='''' ad__qad01='''' ad__qad02='''' ad__qad03='''' ad__qad04='''' ad__qad05='''' ad__chr01='''' ad__chr02='''' ad__chr03='''' ad__chr04='''' ad__chr05='''' ad_tp_loc_code='''' ad_ctry=''MEX'' ad_tax_zone=''MEXICO'' ad_tax_usage=''BUSES'' ad_misc1_id='''' ad_misc2_id='''' ad_misc3_id='''' ad_wk_offset=''0'' ad_inv_mthd='''' ad_sch_mthd='''' ad_po_mt
hd='''' ad_asn_data='''' ad_intr_division='''' ad_tax_report=''0'' ad_name_control='''' ad_last_file=''0'' ad_domain=''VIM'' oid_ad_mstr=''0'' />
.
.
<ad_mstr ad_addr=''SOCIOS4'' ad_name=''COMPANY Y'' ad_line1='''' ad_line2='''' ad_city='''' ad_state='''' ad_zip='''' ad_type=''customer'' ad_attn='''' ad_phone='''' ad_ext='''' ad_ref='''' ad_sort=''COMPANY Y'' ad_country=''MEXICO'' ad_attn2='''' ad_phone2='''' ad_ext2='''' ad_fax='''' ad_fax2='''' ad_line3='''' ad_user1='''' ad_user2='''' ad_lang='''' ad_pst_id='''' ad_date=''02/03/1993'' ad_county='''' ad_temp=''0'' ad_bk_acct1='''' ad_bk_acct2='''' ad_format=''0'' ad_vat_reg='''' ad_coc_reg='''' ad_gst_id='''' ad_tax_type='''' ad_taxc=''1'' ad_taxable=''1'' ad_tax_in=''0'' ad_conrep='''' ad_edi_tpid='''' ad_edi_ctrl='';;;;'' ad_timezone='''' ad_userid='''' ad_edi_id='''' ad_barlbl_prt='''' ad_barlbl_val='''' ad_calendar='''' ad_edi_std='''' ad_edi_level='''' ad__qad01='''' ad__qad02='''' ad__qad03='''' ad__qad04='''' ad__qad05='''' ad__chr01='''' ad__chr02
='''' ad__chr03='''' ad__chr04='''' ad__chr05='''' ad_tp_loc_code='''' ad_ctry=''MEX'' ad_tax_zone=''MEXICO'' ad_tax_usage=''BUSES'' ad_misc1_id='''' ad_misc2_id='''' ad_misc3_id='''' ad_wk_offset=''0'' ad_inv_mthd='''' ad_sch_mthd='''' ad_po_mthd='''' ad_asn_data='''' ad_intr_division='''' ad_tax_report=''0'' ad_name_control='''' ad_last_file=''0'' ad_domain=''VIM'' oid_ad_mstr=''0'' /></NewDataSet>'
DELETE ad_mstr FROM ad_mstr INNER JOIN (SELECT * FROM OPENXML (@hdoc, '/NewDataSet/ad_mstr', 1) WITH ad_mstr) xmltable ON 1 = 1 INSERT INTO ad_mstr SELECT * FROM OPENXML (@hdoc, '/NewDataSet/ad_mstr', 1) WITH ad_mstr EXEC sp_xml_removedocument @hDoc

If I take the sqlText (line 43) value (the whole XML code I pasted above) and test it in an SQL Server Query Analyzer, first I have change all the apostrophes inside the text values (change ARTHUR’S for ARTHUR&apos;S, is this correct ?), then I have an error stating:

Server: Msg 6603, Level 16, State 1, Procedure sp_xml_preparedocument, Line 1
XML parsing error: Missing equals sign between attribute and attribute value.

The server (and the table) where I’m extracting the info is the same that the server (and the table) where I’m trying to insert the info.

Why is this happening ?

I’ve read many articles about wrong encodings and invalid characters but I still don’t get it, can you help me ?

Can you tell me exactly what I should do ?

If you need extra info, please, let me know.

Thanks a lot.

BR,

Francisco

<div class="ForumMod">modified on Friday, April 24, 2009 9:46 AM</div>
GeneralRe: Problem with OPENXML ?, Bulk Insert ?, Encoding ? Pin
llitsanylg28-Aug-09 0:43
llitsanylg28-Aug-09 0:43 
GeneralInserting table with identity column Pin
sriprabu1-May-07 12:24
sriprabu1-May-07 12:24 
GeneralRe: Inserting table with identity column Pin
poodull761-May-07 15:32
poodull761-May-07 15:32 
GeneralRe: Inserting table with identity column Pin
sriprabu5-May-07 1:44
sriprabu5-May-07 1:44 
Generalinsert fails when data contains single quote Pin
breakpoint18-Mar-07 22:54
breakpoint18-Mar-07 22:54 
GeneralRe: insert fails when data contains single quote Pin
poodull7619-Mar-07 2:52
poodull7619-Mar-07 2:52 
GeneralSQL Bulk Insert Pin
rhorc1-Dec-06 13:04
rhorc1-Dec-06 13:04 
Generaldatetime fails! Pin
species217523-Jan-06 3:49
species217523-Jan-06 3:49 
GeneralRe: datetime fails! Pin
poodull7623-Jan-06 4:22
poodull7623-Jan-06 4:22 
GeneralRe: datetime fails! Pin
species217523-Jan-06 20:03
species217523-Jan-06 20:03 
GeneralRe: datetime fails! Pin
sides_dale23-Aug-06 15:20
sides_dale23-Aug-06 15:20 
GeneralPossible way to speed up inserts/ updates Pin
Member 15467162-Oct-05 21:36
Member 15467162-Oct-05 21:36 
GeneralRe: Possible way to speed up inserts/ updates Pin
sides_dale23-Aug-06 15:23
sides_dale23-Aug-06 15:23 
Generalgood concept Pin
MP3Observer15-Jun-05 2:35
MP3Observer15-Jun-05 2:35 
GeneralI have a Pbm with string data types Pin
Sidhartha Shenoy10-Jun-05 23:42
Sidhartha Shenoy10-Jun-05 23:42 
GeneralRe: I have a Pbm with string data types Pin
poodull7614-Jun-05 8:37
poodull7614-Jun-05 8:37 
GeneralRe: I have a Pbm with string data types Pin
Sidhartha Shenoy14-Jun-05 18:15
Sidhartha Shenoy14-Jun-05 18:15 
GeneralBoolean/Bit type Pin
Member 142485530-May-05 23:36
Member 142485530-May-05 23:36 
GeneralRe: Boolean/Bit type Pin
poodull7614-Jun-05 8:31
poodull7614-Jun-05 8:31 
AnswerRe: Boolean/Bit type Pin
sides_dale23-Aug-06 15:18
sides_dale23-Aug-06 15:18 
GeneralRe: Boolean/Bit type Pin
ja92822-Oct-06 9:20
ja92822-Oct-06 9:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.