Best way to transfer an xml to SQL Server? - sql-server

I have been hearing the podcast blog for a while, I hope I dont break this.
The question is this: I have to insert an xml to a database. This will be for already defined tables and fields. So what is the best way to accomplish this? So far I am leaning toward programatic. I have been seeing varios options, one is Data Transfer Objects (DTO), in the SQL Server there is the sp_xml_preparedocument that is used to get transfer XMLs to an object and throught code.
I am using CSharp and SQL Server 2005. The fields are not XML fields, they are the usual SQL datatypes.

In an attempt to try and help, we may need some clarification. Maybe by restating the problem you can let us know if this is what you're asking:
How can one import existing xml into a SQL 2005 database, without relying on the built-in xml type?
A fairly straight forward solution that you already mentioned is the sp_xml_preparedocument, combined with openxml.
Hopefully the following example illustrates the correct usage. For a more complete example checkout the MSDN docs on Using OPENXML.
declare #XmlDocumentHandle int
declare #XmlDocument nvarchar(1000)
set #XmlDocument = N'<ROOT>
<Customer>
<FirstName>Will</FirstName>
<LastName>Smith</LastName>
</Customer>
</ROOT>'
-- Create temp table to insert data into
create table #Customer
(
FirstName varchar(20),
LastName varchar(20)
)
-- Create an internal representation of the XML document.
exec sp_xml_preparedocument #XmlDocumentHandle output, #XmlDocument
-- Insert using openxml allows us to read the structure
insert into #Customer
select
FirstName = XmlFirstName,
LastName = XmlLastName
from openxml ( #XmlDocumentHandle, '/ROOT/Customer',2 )
with
(
XmlFirstName varchar(20) 'FirstName',
XmlLastName varchar(20) 'LastName'
)
where ( XmlFirstName = 'Will' and XmlLastName = 'Smith' )
-- Cleanup xml document
exec sp_xml_removedocument #XmlDocumentHandle
-- Show the data
select *
from #Customer
-- Drop tmp table
drop table #Customer
If you have an xml file and are using C#, then defining a stored procedure that does something like the above and then passing the entire xml file contents to the stored procedure as a string should give you a fairly straight forward way of importing xml into your existing table(s).

If your XML conforms to a particular XSD schema, you can look into using the "xsd.exe" command line tool to generate C# object classes that you can bind the XML to, and then form your insert statements using the properties of those objects: MSDN XSD Doc

Peruse this document and it will give you the options:
MSDN: XML Options in Microsoft SQL Server 2005

You may want to use XSLT to transfer your XML into SQL statements... ie
<xml type="user">
<data>1</data>
<data>2</data>
<xml>
Then the XSLT would look like
<xsl:template match="xml">
INSERT INTO <xsl:value-of select="#type" /> (data1, data2) VALUES (
'<xsl:value-of select="data[1]" />',
'<xsl:value-of select="data[2]" />');
</xsl:template>
The match statement most likely won't be the root node, but hopefully you get the idea. You may also need to wrap the non xsl:value-of parts in xsl:text to prevent extra characters from being dumped into the query. And you'd have to make sure the output of the XSLT was text. That said you could get a list of SQL statements that you could run through the DB. or you could use XSLT to output a T-SQL statement that you could load as a stored procedure.

Related

Insert element into XML using XQuery in SQL Server

I need to insert a column in a stored procedure which reads XML as input and reads the XML value using XQuery in SQL Server.
Consider a table dbo.emailDetails
Create Table dbo.emailDetails
(
EmailId int,
HomeEmail varchar(250),
);
XML file:
<EmailDetails xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EmailId>1</EmailId>
<HomeEmail>test#sample.com</HomeEmail>
</EmailDetails>
SQL Server stored procedure:
CREATE PROCEDURE [apply].[UpdateEmailDetails]
#EmailDetails XML
(DOCUMENT [dbo].[EmailDetails])
AS
BEGIN
DECLARE #EmailId INT, #HomeEmail NVARCHAR(250)
SET #HomeEmail = #EmailDetails.value(N'(//EmailDetails/HomeEmail)[1]',N'NVARCHAR(255)');
SET #EmailId = #EmailDetails.value(N'(//EmailDetails/EmailID)[1]',N'INT');
INSERT INTO dbo.emails (emailid, homeemail)
VALUES (#EmailId, #HomeEmail )
END
Now I would like to include the IsConfirmed in the above stored procedure.
alter table dbo.Emaildetails
add IsConfirmed bit not null default 0
----- Executed successfully and added the new column in the table.
While I tried the below changes in the stored procedure:
Declare #IsConfirmed bit
SET #IsConfirmed = #EmailDetails.value(N'(//EmailDetails/IsConfirmed)[1]',N'BIT');
and got the error:
XQuery [value()]: There is no element named 'IsConfirmed' in the type 'element(EmailDetails,#anonymous) *'.
Could someone help me with this?
Kindly let me know if any details required further.
Regards,
Viswa V.
Your stored procedure has an input parameter which is as follows:
#EmailDetails XML (DOCUMENT [dbo].[EmailDetails])
This means you have an XML Schema Collection named "[dbo].[EmailDetails]" defined which basically says what format the incoming XML should be in.
If you expand the Programmability > Types > XML Schema Collections nodes in your database explorer you will see your "[dbo].[EmailDetails]" schema. If you then right click and select Script as > Create to new window you will see what nodes are expected to be in the XML you pass to your procedure.
You need to ALTER this schema to include a definition for your new
<IsConfirmed>
node.
Once you alter it you should then be able to run your alter procedure command again.
This MSDN article explains more on the topic

Does the command FOR XML in MS SQL Server save the file in disk?

Does the command FOR XML in MS SQL Server save the file in disk?
I'm creating a trigger to log operations in a table and part of this trigger is create a XML with the affected row. I'm thinking of using the FOR XML to generate the XML.
SELECT *
FROM TBL_Test
WHERE ID=3040
FOR XML RAW
My worry is that I will be using it in a trigger and I donĀ“t want to save files in the server every time I call the FOR XML function.
In addition: would you guys know how to parse it to varchar?
Thanks in advance for any help!
Like any SELECT query, a query with the FOR XML clause will return the result to the client and not save the result to disk.
You can use a scalar subquery to assign the result XML to a varchar variable instead of returning to the client:
DECLARE #xml varchar(MAX) =
(
SELECT *
FROM dbo.TBL_Test
WHERE ID=3040
FOR XML RAW
);

SQL Server 2012 Insert XML into table issue

I am trying to create a generic update procedure. The point of this procedure is that we want to be able to track everything that happens in a table. If a recordis updated, we need to be able to know who changed that record, what it was originally, what it is after the change and when the change occurred. We only do this on our most important tables where accountability is a must.
Right now, we do this through a combination of web server programming and SQL Server commands.
I need to take what we currently have, and make a SQL only version.
So, here are the requirements of what I need:
The original sp is called UpdateWithHistory. Right now, it takes 4 parameters all varchar (or it can be nvarchar, doesn't matter). They are the table name, the primary key field, primary key value and a comma delimited list of fields and values in the format field='value',field1='value1'...etc.
In the background, we have a mapping table that we use to map the string table names to actual tables.
In the stored procedure, I have tried various combinations of OPENROWSET, exec(), select into, xml, and other methods. None seem to work.
So basically, I have to be able to dynamically generate a simple select statement (no joins or other complicated select stuff) from the 4 supplied parameters, then store the results of that query in a table. Since it is dynamic, I don't know the number of fields being queried, or what data types they will be.
I tried select into since that will automatically create a table with the appropriate fields and data types, but it doesn't work in conjunction with the exec command. I have also tried
exec sp_executeSQL #SQL, N'#output xml output', #resultXML output
Where #resultXML is XML datatype and #SQL is the sql command. #resultXML always ends up as null, no matter what I do. I also tried the xml route because I know that "FOR XML Path" always returns one column, but I can't use that in an insert into statement....
That statement output will be used to determine the original values before the update.
I figure once I get past this hurdle the rest will be a piece of cake. Anyone got any ideas?
So here is code for something that I finally got to work, although I don't want to use global tables, so I would gladly accept a different answer...
DECLARE #curRecordString varchar(max) = 'SELECT * into ##TEMP_TABLE FROM SOMEDB.dbo.' + #tbl + ' WHERE ' + #prikey + ' = ''' + #prival + ''' '
exec(#curRecordString)
Basically, as stated before, I need to dynamically build a sql query, then store the result of running the query so that I can access it later. I would prefer to store it as XML datatype, since I will later be using XQuery to parse and compare nodes. In the code above, I am using a global temp table (not ideal, I know) to store the result of the query so that the rest of my procedure can access the data.
Like I said, I don't like this approach but hopefully someone else can come up with something better that will allow me to dynamically build a SQL query, run it, store the results so that I can access the results later in the stored procedure.
This is most definitely a hack, but...
DECLARE #s VARCHAR(MAX)
SET #s = 'SELECT (SELECT 1 as splat FOR XML PATH) a'
CREATE TABLE #save (x XML)
INSERT INTO #save
( x )
EXEC (#s)
SELECT * FROM #save s
DROP TABLE #save

Converting UTF8 to uTF16 in SQL Server

I have an application that receives XML from some web service written in PHP and inserts it to SQL Server database. When I try to insert received XML that contains Polish diacritical characters, I get an error like this:
XML parsing: line 2, character 703, illegal xml character
I tried to do something like this:
DECLARE #xml XML;
SET #xml = '(here I paste some sample XML that contains diacritical characters)';
SELECT #xml = CAST(#xmlstr AS XML);
INSERT INTO vos_DirectXML_ut(ValidXML,synchronization_time,synchronization_type,MethodName)
VALUES(#xml,GETDATE(),#SynchroType,#method);
ValidXML is a XML type column.
I googled to find some solution and I found Utf8String:
http://msdn.microsoft.com/en-us/library/ms160893(v=sql.90).aspx
I installed it, and tried to convert XML to Utf8String and then convert it again to normal varchar, and then to XML, and insert it to my table, but looks like it does not changes any characters inside of this XML, it just changes type of variable and it didn't solve my problem.
I also found some guy's advice that it's possible to solve similar problem by writing a procedure that goes through loop for every character in variable (XML in my case) and manually change it's encoding, but this guy also said that it may work slow. Is this really the only option to solve my problem?
Try cast to UNICODE:
DECLARE #xmlstr NVARCHAR(MAX) --<--
SELECT #xmlstr = N'(some sample XML that contains diacritical characters)'; --<-- N''
DECLARE #xml XML
SELECT #xml = CAST(#xmlstr AS XML)
INSERT INTO dbo.vos_DirectXML_ut
(
ValidXML
, synchronization_time
, synchronization_type
, MethodName
)
SELECT
#xml
, GETDATE()
, #SynchroType
, #method
for XML file , UTF-16 is not supported by SQL server 2008 R2 ,so for the xml file,which is starts with
when you parse this xml gives error
Msg 6602, Level 16, State 2, Procedure sp_xml_preparedocument, Line 1
The error description is 'Switch from current encoding to specified encoding not supported.'.
to resolve the above error the easy step is to use the SQL replace function
REPLACE('#xmldata','utf-16','') or REPLACE('#xmldata','utf-16','utf-8')
I have worked on 3 procedures using an xml file,whenever i tried to use utf-16 XML parser gives error.
Always use utf-8 for SQL server 2008 R2

SSIS 2008 - import xml file contents into sql server

I want to take a series of xml files and pull the xml of the file into a table in the database. I have a for each file enumerator, then an xml task to pull out the dtd and put the contents in a variable. Now that I have the file name and the contents in a variable, I need to insert both pieces of data into the database.
My table to store the data looks like this:
create table Import_Files
(
SequenceId int IDENTITY(1,1) NOT NULL,
FileName varchar(200) NOT NULL,
FileXml xml NOT NULL,
Created datetime DEFAULT(GETDATE()) NOT NULL,
Processed bit DEFAULT(0) NOT NULL
)
My Stored procedure:
CREATE PROCEDURE [dbo].[AddFile]
#FileName varchar(200),
#FileXml xml
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--Add new record
INSERT INTO Import_Files
([FileName], FileXml)
VALUES
(#FileName, #FileXml)
END
I can't get it to work because hte xml data type isn't available in my execute sql task. Any ideas on how to make this work?
I would look at the import column transformation. It allows you to import the contents of a file for each row in a dataflow. The data source would simply be a listing of each file and any other column level meta data you need.
This would probably be more performant then doing a row by row insert from a spro
More info on setting this up here:
http://msdn.microsoft.com/en-us/library/ms141262.aspx
Have you tried using a string datatype?
As sugested earlier change the proc to accept a string datatype varchar(max) and do a convert to xml in the proc if you must store it in an xml column
Instead of using an Execute SQL Task, I would use an XML Source - generate all the fields you wanted into columns and then just pass those into the database table using an OLE DB Destination. This way you don't have to even use your stored procedure since SSIS already would do these inserts for you and it would recognize your xml type.
I had to use a Script task and call the sproc through code.

Resources