Insert into select in SQL server - sql-server

I am trying to convert data table to xml. It works fine. I want to store this converted xml in another table, So I tried using insert into select statement but it throws an error
The FOR XML clause is not allowed in a INSERT statement.
My query:
insert into table1 (column1)
select * from table2
for xml raw('product'),root('productDetails');

Updated :
This is tougher than i thought . what we have to do is
Save Xml in variable
then save Variable data to Table.(I think this can be simplified )
Code :
CREATE TABLE #MyXMLTable
(
xCol XML
) ;
DECLARE #testXML XML
SET #testXML = (
select * from "Product"
FOR XML RAW ('Product'), ROOT ('Products'));
select #testXML ;
INSERT INTO #MyXMLTable ( xCol )
SELECT #testXML;
SELECT * from #MyXMLTable
using-the-for-xml-clause-to-return-query-results-as-xml
insert-transact-sql

Related

How to write an SQL Select for XML including Union logic?

I have the following statement to get both dates into #xmlData
declare #xmlData OUTOUT
SET #xmlData = (SELECT #FileDate AS [FileDate] UNION SELECT #satDate AS [FileDate] FOR XML RAW, ELEMENTS)
Then I will insert it into the table:
DECLARE #ListOfDates TABLE (FileDate varchar(50))
INSERT #ListOfDates (FileDate)
SELECT Tbl.Col.value('FileDate[1]', 'varchar(50)')
FROM #xmlData.nodes('//row') Tbl(Col)
When executing my select logic, I'm getting an error saying:
The FOR XML and FOR JSON clauses are invalid in views, inline
functions, derived tables, and subqueries when they contain a set
operator. To work around, wrap the SELECT containing a set operator
using derived table or common table expression or view and apply FOR
XML or FOR JSON on top of it.
How to fix that?
I don't see why you're using XML at all here. But the error is telling you to push down that query into a derived table (subquery) or CTE, like this:
declare #xmlData xml
declare #filedate date = getdate()
declare #satdate date = '20140101'
SET #xmlData = (
select * from
( SELECT #FileDate AS [FileDate] UNION ALL SELECT #satDate AS [FileDate] ) d
FOR XML RAW, ELEMENTS, type
)
select #xmlData

How can I fix the error : Multi-Part ID when update a field of #tempTable

I want to compare #tempTable with tableA, if matched then update FieldValue of #tempTable equal to id of tableA; if not matched then insert values ,and get the id of tableA to update FieldValue of #tempTable.
The following is my SQL query:
create table [dbo].[TableA]([Id] int Indentity(1,1),[Data] [sql_variant] NULL)
declare #tempTable table (FieldValue nvarchar(1000),FieldType nvarchar(1000))
insert #tempTable values ('some content','A Type')
merge
tableA
using (
select
FieldValue
from
#tempTable
) x
on tableA.[Data] = x.FieldValue
when not matched then
insert values (x.FieldValue)
when matched then
update set x.FieldValue = tableA.[Id] ;
The following is the error message:
Unable to tie the Multi-Part ID "x.FieldValue".
The error looks like it's different data type between x.FieldValue and tableA.id, so I adjust them to the same data type, but it's still not work, and I don't know how to fix it.
What are you trying to achieve? Your target table is tableA, your source table is the x-aliased sub-query.
Next time please try to create a mcve. I had to modify your code slightly, but you will get the ghist:
declare #TableA TABLE([Id] int,[Data] [sql_variant] NULL)
declare #tempTable table (FieldValue nvarchar(1000),FieldType nvarchar(1000))
insert #tempTable values ('some content','A Type');
merge
#tableA a
using (
select
FieldValue
from
#tempTable
) x
on a.[Data] = x.FieldValue
when matched then
update set a.id = x.FieldValue; --fields swapped, probably not really your intention...
The point is: Your code tries to update a field of your source table. The general idea of MERGE is
We target one table where we want to insert/update/delete some records.
We use a second set with the data we want to compare and use for these operations
We find rows within the source which are missing in the target -> INSERT
We find rows within the source which are existing in the target -> UPDATE
We find rows whithin the target which are missing in the source -> DELETE
Saying this, I doubt, that the code above would need MERGE at all...
The following can achieve the results I want.
merge
tableA
using (
select
FieldValue
from
#tempTable
) x
on tableA.[Data] = x.FieldValue
when not matched then
insert values (x.FieldValue);
update #tempTable
set t.FieldValue = i.[Id]
from #tempTable t
join TableA i ON i.[Data] = t.FieldValue
select * from #tempTable

Pulling a value from Xml in a column

I have a table in Sql server that stores Xml data in one of its columns.
The Xml column data looks like this:
<TestDef Weight="0" FailValue="2" ConceptID="-327">
<ToleranceDef ObjectType="SomeName" TargetValue="0"TargetRange="2" />
</TestDef>
I need to write a query that fetches out all the conceptId's from each rows Xml column.
Here it would be -327
I know I can cast the Xml column to a nvarchar(max) then use some reg exp to get the value but not sure how to use the regular expression
Here's an example using a table variable. It will be the same concept with an actual table:
Declare #XmlTable table (
Id Integer Identity,
XmlValue XML
)
Insert Into #XmlTable (XmlValue) values ('<TestDef Weight="0" FailValue="2" ConceptID="-327"><ToleranceDef ObjectType="SomeName" TargetValue="0" TargetRange="2" /></TestDef>')
Insert Into #XmlTable (XmlValue) values ('<TestDef Weight="0" FailValue="2" ConceptID="-325"><ToleranceDef ObjectType="SomeName" TargetValue="0" TargetRange="2" /></TestDef>')
select
Id,
XmlValue,
XmlValue.value('(/TestDef/#ConceptID)[1]', 'integer') as ConceptId
from
#XmlTable

SQL Server table to xml

this time i have question how to convert MSSQL table to XML
My source SQL table:
+-----------+-----------------+
|atributname|atributvalue |
+-----------+-----------------+
|phone |222 |
|param4 |bbbbcdsfceecc |
|param3 |bbbbcdsfceecc |
|param2 |bbbbcdsfccc |
+-----------+-----------------+
Expected result sample:
<items>
<phone>222</phone>
<prama4>bbbbcdsfceecc</param4>
<param3>bbbbcdsfceecc</param3>
<param2>bbbbcdsfccc</param2>
</items>
I tried lot of variations of the following query
SELECT atributname,atributvalue
FROM sampletable FOR XML PATH (''), ROOT ('items');
but results are not good :( should be exactly like in "Expected result sample"
any help
ps
Script to create sampletable:
create table sampletable
(atributname varchar(20),
atributvalue varchar(20))
insert into sampletable (atributname,atributvalue)
values ('phone','222');
insert into sampletable (atributname,atributvalue)
values ('param4','bbbbcdsfceecc');
insert into sampletable (atributname,atributvalue)
values ('param3','bbbbcdsfceecc');
insert into sampletable (atributname,atributvalue)
values ('param2','bbbbcdsfccc');
That's not how FOR XML works. It's columns that get turned into XML elements, not rows. In order to obtain the expected result, you would need to have columns named phone, param4, and so on - not rows with these values in attributename.
If there are specific elements you want in the XML, you could perform a pivot on the data first, then use FOR XML.
Example of a pivot would be:
SELECT [phone], [param2], [param3], [param4]
FROM
(
SELECT attributename, attributevalue
FROM attributes
) a
PIVOT
(
MAX(attributevalue)
FOR attributename IN ([phone], [param2], [param3], [param4])
) AS pvt
FOR XML ROOT('items')
Of course the aggregate will only work if attributevalue is a numeric data type. If it's a character-type column, then you'll have some trouble with the pivot, as there are no built-in string aggregates in SQL server AFAIK...
ok
finally i have done this in several ways,
but this is simplest version suitable for medium dataset
declare #item nvarchar(max)
set #item= (SELECT '<' + atributname +'>' +
cast(atributvalue as nvarchar(max)) +'</' + atributname +'>'
FROM sampletable FOR XML PATH (''), ROOT ('items'));
select replace(replace(#item,'<','<'),'>','>')

SQL Server: Output an XML field as tabular data using a stored procedure

I am using a table with an XML data field to store the audit trails of all other tables in the database.
That means the same XML field has various XML information. For example my table has two records with XML data like this:
1st record:
<client>
<name>xyz</name>
<ssn>432-54-4231</ssn>
</client>
2nd record:
<emp>
<name>abc</name>
<sal>5000</sal>
</emp>
These are the two sample formats and just two records. The table actually has many more XML formats in the same field and many records in each format.
Now my problem is that upon query I need these XML formats to be converted into tabular result sets.
What are the options for me? It would be a regular task to query this table and generate reports from it. I want to create a stored procedure to which I can pass that I need to query "<emp>" or "<client>", then my stored procedure should return tabular data.
does this help?
INSERT INTO #t (data) SELECT '
<client>
<name>xyz</name>
<ssn>432-54-4231</ssn>
</client>'
INSERT INTO #t (data) SELECT '
<emp>
<name>abc</name>
<sal>5000</sal>
</emp>'
DECLARE #el VARCHAR(20)
SELECT #el = 'client'
SELECT
x.value('local-name(.)', 'VARCHAR(20)') AS ColumnName,
x.value('.','VARCHAR(20)') AS ColumnValue
FROM #t
CROSS APPLY data.nodes('/*[local-name(.)=sql:variable("#el")]') a (x)
/*
ColumnName ColumnValue
-------------------- --------------------
client xyz432-54-4231
*/
SELECT #el = 'emp'
SELECT
x.value('local-name(.)', 'VARCHAR(20)') AS ColumnName,
x.value('.','VARCHAR(20)') AS ColumnValue
FROM #t
CROSS APPLY data.nodes('/*[local-name(.)=sql:variable("#el")]') a (x)
/*
ColumnName ColumnValue
-------------------- --------------------
emp abc5000
*/
Neither xyz432-54-4231 nor abc5000 is valid XML.
You can try to select only one particular format with a like statement, f.e.:
select *
from YourTable
where YourColumn like '[a-z][a-z][a-z][0-9][0-9][0-9][0-9]'
This would match 3 letters followed by 4 numbers.
A better option is probably to add an extra column to the table, where you save the type of the logging. Then you can use that column to select all "emp" or "client" rows.
An option would be to create a series of views that present the aduit table, per type in the relations that you're execpting
for example
select
c.value('name','nvarchar(50)') as name,
c.value('ssn', 'nvarchar(20)') as ssn
from yourtable
cross apply yourxmlcolumn.nodes('/client') as t(c)
you could then follow the same pattern for the emp
you could also create a view (or computed column) to identify each xml type like this:
select yourxmlcolumn.value('local-name(/*[1])', 'varchar(100)') as objectType
from yourtable
Use open xml method
DECLARE #idoc int
EXEC sp_xml_preparedocument #idoc OUTPUT, #xmldoc
SELECT * into #test
FROM OPENXML (#idoc, 'xmlfilepath',2)
WITH (Name varchar(50),ssn varchar(20)
)
EXEC sp_xml_removedocument #idoc
after you get the data in the #test
and you can manipulate this.
you may be put the diff data in diff xml file.

Resources