Special For Xml in SqlServer - sql

we have a simple table and need convert to XML
Declare #Person TABLE
( [BusinessEntityID] [int] NOT NULL,
[PersonType] [varchar](2) NULL,
[Title] [varchar](30) NULL,
[FirstName] [varchar](30) NULL,
[MiddleName] [varchar](30) NULL,
[LastName] [varchar](30) NULL)
Insert Into #Person Values(10001,'IN','Article','Carolyn','Jo','Alonso')
we need this xml for output with For XML in sql server
<?xml-stylesheet type='text/xsl' href='result.xsl'?>
<documents>
<document>
<field name="BusinessEntityID">10001</field>
<field name="PersonType">IN</field>
<field name="Title">Article</field>
<field name="FirstName">Carolyn</field>
<field name="MiddleName">Jo</field>
<field name="LastName">Alonso</field>
</document>
</documents>

The following XML PATH query should get you most of the way. You just need to add the stylesheet header.
SELECT
'BusinessEntityID' AS 'document/field/#name'
, BusinessEntityID AS 'document/field'
, '' AS 'document'
, 'documentType' AS 'document/field/#name'
, PersonType AS 'document/field'
, '' AS 'document'
, 'Title' AS 'document/field/#name'
, Title AS 'document/field'
, '' AS 'document'
, 'FirstName' AS 'document/field/#name'
, FirstName AS 'document/field'
, '' AS 'document'
, 'MiddleName' AS 'document/field/#name'
, MiddleName AS 'document/field'
, '' AS 'document'
, 'LastName' AS 'document/field/#name'
, LastName AS 'document/field'
, '' AS 'document'
FROM #Person
FOR XML PATH(''), ROOT('documents')

Related

How do I group multiple nested XML in SQL with FOR XML PATH depending on the column

I have a query that formats my results in an XML. Although it is the format that I need it to be, it's not grouping the necessary columns I need it to be grouped by.
SELECT (SELECT BatchNumber,
TotalCount,
CAST(TotalAmount AS decimal(18,2)) AS TotalAmount,
TotalRetainage
FOR XML PATH('Summary'), TYPE) ,
(SELECT ( SELECT 'Success' AS ProcessStatus,
'' AS ProcessMessage,
BatchNumber AS BatchNumber,
'' AS TransactionNumber,
'' AS VoidedDate
FOR XML PATH('Response'), TYPE),
AddressNumber,
Amount,
BusinessUnit,
Company,
DateGL,
DateInvoice,
DocumentType,
DocumentNumber,
GLOffset,
LineNumber,
NameRemark,
PayStatusCode,
PaymentHandlingCode,
SupplierInvoiceNumber,
(SELECT DetailAccountModeGL AS AccountModeGL,
DetailAccountNumberInput AS AccountNumberInput,
DetailAmount AS Amount,
DetailLedgerTypes LedgerTypes,
DetailLineNumber AS LineNumber,
DetailNameAlphaExplanation AS NameAlphaExplanation,
DetailNameRemarkExplanation AS NameRemarkExplanation,
DetailObjectAccount AS ObjectAccount,
DetailSubledgerGL AS SubledgerGL,
DetailSubledgerType AS SubledgerType,
DetailSubsidiary AS Subsidiary
FOR XML PATH('Details'), TYPE)
FOR XML PATH('Invoice'), TYPE, ROOT('Invoices'))
FROM #ExpenseConsolidated
FOR XML PATH('InvoiceIntegrationBatch')
This is the result I'm getting back
<InvoiceIntegrationBatch>
<Summary>
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TotalCount>2</TotalCount>
<TotalAmount>0.00</TotalAmount>
<TotalRetainage>0</TotalRetainage>
</Summary>
<Invoices>
<Invoice>
<Response>
<ProcessStatus>Success</ProcessStatus>
<ProcessMessage />
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TransactionNumber />
<VoidedDate />
</Response>
<AddressNumber>0.000000000000000e+000</AddressNumber>
<Amount>2.390000000000000e+005</Amount>
<BusinessUnit> 4362</BusinessUnit>
<Company>04362</Company>
<DateGL>116173</DateGL>
<DateInvoice>116173</DateInvoice>
<DocumentType>JG</DocumentType>
<DocumentNumber>1.599032800000000e+007</DocumentNumber>
<GLOffset> </GLOffset>
<LineNumber>0.000000000000000e+000</LineNumber>
<NameRemark> </NameRemark>
<PayStatusCode> </PayStatusCode>
<PaymentHandlingCode> </PaymentHandlingCode>
<SupplierInvoiceNumber> </SupplierInvoiceNumber>
<Details>
<AccountModeGL>2</AccountModeGL>
<AccountNumberInput> 4362.10410.582 </AccountNumberInput>
<Amount>2.390000000000000e+005</Amount>
<LedgerTypes>AA</LedgerTypes>
<LineNumber>1.000000000000000e+000</LineNumber>
<NameAlphaExplanation>TEST Alpha Explanation</NameAlphaExplanation>
<NameRemarkExplanation>Test Name Remark Explanation</NameRemarkExplanation>
<ObjectAccount>10410 </ObjectAccount>
<SubledgerGL>2016 </SubledgerGL>
<SubledgerType>X</SubledgerType>
<Subsidiary>582 </Subsidiary>
</Details>
</Invoice>
</Invoices>
</InvoiceIntegrationBatch>
<InvoiceIntegrationBatch>
<Summary>
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TotalCount>2</TotalCount>
<TotalAmount>0.00</TotalAmount>
<TotalRetainage>0</TotalRetainage>
</Summary>
<Invoices>
<Invoice>
<Response>
<ProcessStatus>Success</ProcessStatus>
<ProcessMessage />
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TransactionNumber />
<VoidedDate />
</Response>
<AddressNumber>0.000000000000000e+000</AddressNumber>
<Amount>-2.390000000000000e+005</Amount>
<BusinessUnit> 4362</BusinessUnit>
<Company>04362</Company>
<DateGL>116173</DateGL>
<DateInvoice>116173</DateInvoice>
<DocumentType>JG</DocumentType>
<DocumentNumber>1.599032800000000e+007</DocumentNumber>
<GLOffset> </GLOffset>
<LineNumber>0.000000000000000e+000</LineNumber>
<NameRemark> </NameRemark>
<PayStatusCode> </PayStatusCode>
<PaymentHandlingCode> </PaymentHandlingCode>
<SupplierInvoiceNumber> </SupplierInvoiceNumber>
<Details>
<AccountModeGL>2</AccountModeGL>
<AccountNumberInput> 4362.10410.580 </AccountNumberInput>
<Amount>-2.390000000000000e+005</Amount>
<LedgerTypes>AA</LedgerTypes>
<LineNumber>2.000000000000000e+000</LineNumber>
<NameAlphaExplanation>Test Alpha Explanation 2</NameAlphaExplanation>
<NameRemarkExplanation>Test Name Remark Explanation 2</NameRemarkExplanation>
<ObjectAccount>10410 </ObjectAccount>
<SubledgerGL>2016 </SubledgerGL>
<SubledgerType>X</SubledgerType>
<Subsidiary>580 </Subsidiary>
</Details>
</Invoice>
</Invoices>
</InvoiceIntegrationBatch>
But what I actually need is the Invoices Grouped together cause all of this is under one batch like the XML below:
<InvoiceIntegrationBatch>
<Summary>
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TotalCount>2</TotalCount>
<TotalAmount>0.00</TotalAmount>
<TotalRetainage>0</TotalRetainage>
</Summary>
<Invoices>
<Invoice>
<Response>
<ProcessStatus>Success</ProcessStatus>
<ProcessMessage />
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TransactionNumber />
<VoidedDate />
</Response>
<AddressNumber>0.000000000000000e+000</AddressNumber>
<Amount>2.390000000000000e+005</Amount>
<BusinessUnit> 4362</BusinessUnit>
<Company>04362</Company>
<DateGL>116173</DateGL>
<DateInvoice>116173</DateInvoice>
<DocumentType>JG</DocumentType>
<DocumentNumber>1.599032800000000e+007</DocumentNumber>
<GLOffset> </GLOffset>
<LineNumber>1</LineNumber>
<NameRemark> </NameRemark>
<PayStatusCode> </PayStatusCode>
<PaymentHandlingCode> </PaymentHandlingCode>
<SupplierInvoiceNumber> </SupplierInvoiceNumber>
<Details>
<AccountModeGL>2</AccountModeGL>
<AccountNumberInput> 4362.10410.582 </AccountNumberInput>
<Amount>2.390000000000000e+005</Amount>
<LedgerTypes>AA</LedgerTypes>
<LineNumber>1.000000000000000e+000</LineNumber>
<NameAlphaExplanation>TEST Alpha Explanation</NameAlphaExplanation>
<NameRemarkExplanation>Test Name Remark Explanation</NameRemarkExplanation>
<ObjectAccount>10410 </ObjectAccount>
<SubledgerGL>2016 </SubledgerGL>
<SubledgerType>X</SubledgerType>
<Subsidiary>582 </Subsidiary>
</Details>
</Invoice>
<Invoice>
<Response>
<ProcessStatus>Success</ProcessStatus>
<ProcessMessage />
<BatchNumber>6.777209000000000e+006</BatchNumber>
<TransactionNumber />
<VoidedDate />
</Response>
<AddressNumber>0.000000000000000e+000</AddressNumber>
<Amount>-2.390000000000000e+005</Amount>
<BusinessUnit> 4362</BusinessUnit>
<Company>04362</Company>
<DateGL>116173</DateGL>
<DateInvoice>116173</DateInvoice>
<DocumentType>JG</DocumentType>
<DocumentNumber>1.599032800000000e+007</DocumentNumber>
<GLOffset> </GLOffset>
<LineNumber>2</LineNumber>
<NameRemark> </NameRemark>
<PayStatusCode> </PayStatusCode>
<PaymentHandlingCode> </PaymentHandlingCode>
<SupplierInvoiceNumber> </SupplierInvoiceNumber>
<Details>
<AccountModeGL>2</AccountModeGL>
<AccountNumberInput> 4362.10410.580 </AccountNumberInput>
<Amount>-2.390000000000000e+005</Amount>
<LedgerTypes>AA</LedgerTypes>
<LineNumber>2.000000000000000e+000</LineNumber>
<NameAlphaExplanation>Test Alpha Explanation 2</NameAlphaExplanation>
<NameRemarkExplanation>Test Name Remark Explanation 2</NameRemarkExplanation>
<ObjectAccount>10410 </ObjectAccount>
<SubledgerGL>2016 </SubledgerGL>
<SubledgerType>X</SubledgerType>
<Subsidiary>580 </Subsidiary>
</Details>
</Invoice>
</Invoices>
</InvoiceIntegrationBatch>
Please note that I am aware that the datatypes are messed up at the moment. But I've been banging my head with how to group these together properly.
Below are test data creates and inserts
CREATE TABLE #ExpenseConsolidated (
TotalCount int,
TotalAmount decimal(18,2),
TotalRetainage decimal(18,2),
BatchNumber varchar(200),
AddressNumber varchar(200),
Amount decimal(18,2),
BusinessUnit varchar(200),
Company varchar(200),
DateGL varchar(200),
DateInvoice varchar(200),
DocumentType varchar(200),
DocumentNumber varchar(200),
GLOffset varchar(200),
LineNumber varchar(200),
NameRemark varchar(200),
PayStatusCode varchar(200),
PaymentHandlingCode varchar(200),
SupplierInvoiceNumber varchar(200),
DetailAccountModeGL varchar(200),
DetailAccountNumberInput varchar(200),
DetailAmount decimal(18,2),
DetailLedgerTypes varchar(200),
DetailLineNumber varchar(200),
DetailNameAlphaExplanation varchar(200),
DetailNameRemarkExplanation varchar(200),
DetailObjectAccount varchar(200),
DetailSubledgerGL varchar(200),
DetailSubledgerType varchar(200),
DetailSubsidiary varchar(200),
DetailReverseVoid varchar(200)
)
INSERT INTO #ExpenseConsolidated
SELECT 2,0,0,'6777209', '0', 239000, ' 4362', '04362', '116173', '116173', 'JG', '15990328', ' ', '0', '', '', '', '', '2', ' 4362.10410.582 ', 239000, 'AA', '1', 'Reclass Consultant Fee Sample1', 'Sample1', '10410 ', '2016 ', 'X', '582 ' , ' '
UNION
SELECT 2,0,0,'6777209', '0', -239000, ' 4362', '04362', '116173', '116173', 'JG', '15990328', ' ', '0', '', '', '', '', '2', ' 4362.10410.580 ', -239000, 'AA', '2', 'Reclass Consultant Fee Sample2', 'Sample2', '10410 ', '2016 ', 'X', '580 ' , ' '
SELECT
(SELECT TOP 1 REPLACE(REPLACE(REPLACE(CONVERT(varchar, GETDATE(), 20), '-', ''), ' ', ''), ':','') AS BatchNumber,
TotalCount,
TotalAmount,
TotalRetainage
FROM #ExpenseConsolidated FOR XML PATH ('Summary'), ELEMENTS, TYPE),
(SELECT ( SELECT 'Success' AS ProcessStatus,
'' AS ProcessMessage,
BatchNumber AS BatchNumber,
'' AS TransactionNumber,
'' AS VoidedDate
FOR XML PATH('Response'), TYPE),
AddressNumber,
Amount,
BusinessUnit,
Company,
DateGL,
DateInvoice,
DocumentType,
DocumentNumber,
GLOffset,
LineNumber,
NameRemark,
PayStatusCode,
PaymentHandlingCode,
SupplierInvoiceNumber,
(SELECT DetailAccountModeGL AS AccountModeGL,
DetailAccountNumberInput AS AccountNumberInput,
DetailAmount AS Amount,
DetailLedgerTypes LedgerTypes,
DetailLineNumber AS LineNumber,
DetailNameAlphaExplanation AS NameAlphaExplanation,
DetailNameRemarkExplanation AS NameRemarkExplanation,
DetailObjectAccount AS ObjectAccount,
DetailSubledgerGL AS SubledgerGL,
DetailSubledgerType AS SubledgerType,
DetailSubsidiary AS Subsidiary
FOR XML PATH('Details'), TYPE)
FROM #ExpenseConsolidated
FOR XML PATH('Invoice'), ROOT('Invoices'), ELEMENTS, TYPE)
FOR XML PATH('InvoiceIntegrationBatch')
I apologize for the horribly formatted question. But this link below is what saved me
Combine XML from T-SQL
I basically just split out the totals by doing a top 1, then just combined Invoices

Using SELECT within Trigger

A customer needs a trigger for his new management tool. It works so far, but now he wants to get values from another table.
What does it mean? Take a short look at the (working) trigger:
CREATE OR REPLACE TRIGGER reldb_export_T_Import3_In
AFTER UPDATE OR INSERT OR DELETE ON infor.RELDB
FOR EACH ROW
DECLARE KST varchar(1000 BYTE);
BEGIN
IF (:new.ZUST = 4 AND :old.ZUST = 3 AND :old.SAINT = 60)
THEN
INSERT INTO infor2infoboard.T_Import3_In
(Idx, Timestamp, ObjectId, Text, RowUid, GroupName, GroupIndex, PredTimeCondition, PredGapValue, Service, ReqQuan, ReqDur,
Efficiency, BackColor, HighlightColor, Brightness, CellOffsetY, Fixed, Font, FontColor, Height, EarliestStart, LastDeliveryDate, RoleId,
StatusIds, WithReservation, LastChange, LastEditedBy, Opacity, IsProcess, CheckSymbol, Link, Priority, IconPath, Adress, CA1, CA2,
CA3, CA4, CA5, CA6, CA7, CA8, CA9, CA10, CA11, CA12, CA13, CA14, CA15,
CA16, CA17, CA18, CA19, CA20, CA21, CA22, CA23, CA24, CA25,
CA26, CA27, CA28, CA29, CA30, CA31, CA32)
VALUES
(seq_t_import3_in.nextval, sysdate, :old.RNR, NULL, CASE WHEN :NEW.KST = '3710' THEN 'Pool TB-M 1;Pool TB-M 2;Pool TB-M 3;Pool TB-M 4;Pool TB-M 5' ELSE KST END, :old.Komm, NULL, NULL, NULL, :old.KTXT, :old.TA_4, NULL,
NULL, CASE WHEN :new.MNR = '3740' THEN 'GREEN' WHEN :new.MNR != '3740' THEN 'BLUE' END, NULL, NULL, NULL, NULL, NULL, NULL, NULL, :old.TERM_2, :old.TERM_1, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, SUBSTR(:old.ANR, 1, 10), :old.KOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
END IF;......
Now he want to replace one of the last NULLS with a selected value.
The statement should look like this:
SELECT KTXT FROM RELDB WHERE ANR = :old.ANR and SAEXT = 'H';
So, for example:
NULL, (SELECT KTXT FROM RELDB WHERE ANR = :old.ANR and SAEXT = 'H';), SUBSTR(:old.ANR, 1, 10), :old.KOMM, NULL
My problem: I'm getting an error, that the trigger couldn't notice some changes. The trigger won't get fired.
So does anyone know how I can use or how I can get selected values (from the same (!!!) table which the trigger is listening to?
I'd appreciate your help :)
Cheers,
Dom
In Oracle, you cannot select from the same table you are changing, this is the mutating table error. See https://asktom.oracle.com/pls/apex/f?p=100:11:0::::p11_question_id:9579487119866

Creating XML from SQL data

I have a huge XML, with over 150 element and attributes. I need to populate only a handful of them ( 5 or 6) elements with data from a SQL server 2008 tables. This created xml need to be passed to a webservice ( to ESB) and this has to happen on a daily schedule.
I think, it does not make sense to use XML Path here to create the XML and use SSIS. Can anyone suggest an approach?
This is the sample XML. I need just the names, address and a few ids populated
<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName></FirstName>
<LastName></LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
<CustomerData>
</CustomerData>
</Customer>
One approach is to take an empty version of your XML document and assign it to an NVARCHAR(MAX) variable. For each node or parameter you wish to populate, put a "token" and use the replace function to populate the value. For example:
DECLARE #xml NVARCHAR(MAX)
SET #xml = N'<Company name="~company_name~">
<Department name="~dept_name~">
<Employee name="~employee_name~" title="~employee_title~" />
</Department>
</Company>'
SET #xml = REPLACE(#xml,N'~company_name~','Microsoft')
SET #xml = REPLACE(#xml,N'~dept_name~','Executive')
SET #xml = REPLACE(#xml,N'~employee_name~','Satya Nadella')
SET #xml = REPLACE(#xml,N'~employee_title~','CEO')
SELECT CAST(#xml AS XML)
Here's a more traditional approach. You'll need an arbitrary value in the cells you wish to update:
DECLARE #example_data TABLE
(FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255) NOT NULL,
Gender CHAR(1) NOT NULL,
City VARCHAR(255) NOT NULL,
[State] CHAR(2) NOT NULL)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Satya' , -- FirstName - varchar(255)
'Nadella' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Redmond' , -- City - varchar(255)
'WA' -- State - char(2)
)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Larry' , -- FirstName - varchar(255)
'Ellison' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Woodside' , -- City - varchar(255)
'CA' -- State - char(2)
)
DECLARE
#customer_xml XML,
#xml XML,
#temp NVARCHAR(255),
#FirstName VARCHAR(255),
#LastName VARCHAR(255),
#Gender CHAR(1),
#City VARCHAR(255),
#State CHAR(2)
SET #customer_xml = '<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName>a</FirstName>
<LastName>b</LastName>
<Gender>c</Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City>d</City>
<State>e</State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
</Customer>'
DECLARE xml_cursor CURSOR FOR
SELECT FirstName , LastName , Gender , City , [State]
FROM #example_data
OPEN xml_cursor
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
WHILE ##fetch_status = 0
BEGIN
SET #xml = #customer_xml
SET #xml.modify('
replace value of (/Customer/CustomerData/FirstName[1]/text())[1]
with sql:variable("#FirstName")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/LastName[1]/text())[1]
with sql:variable("#LastName")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Gender[1]/text())[1]
with sql:variable("#Gender")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Addresses/BillingAddress/City[1]/text())[1]
with sql:variable("#City")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Addresses/BillingAddress/State[1]/text())[1]
with sql:variable("#State")
')
select #xml
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
END
This approach does not require a value in the nodes to be updated. It simply inserts a new node, then deletes the old node:
DECLARE #example_data TABLE
(FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255) NOT NULL,
Gender CHAR(1) NOT NULL,
City VARCHAR(255) NOT NULL,
[State] CHAR(2) NOT NULL)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Satya' , -- FirstName - varchar(255)
'Nadella' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Redmond' , -- City - varchar(255)
'WA' -- State - char(2)
)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Larry' , -- FirstName - varchar(255)
'Ellison' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Woodside' , -- City - varchar(255)
'CA' -- State - char(2)
)
DECLARE
#customer_xml XML,
#xml XML,
#temp NVARCHAR(255),
#FirstName VARCHAR(255),
#LastName VARCHAR(255),
#Gender CHAR(1),
#City VARCHAR(255),
#State CHAR(2)
SET #customer_xml = '<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName></FirstName>
<LastName></LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
</Customer>'
DECLARE xml_cursor CURSOR FOR
SELECT FirstName , LastName , Gender , City , [State]
FROM #example_data
OPEN xml_cursor
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
WHILE ##fetch_status = 0
BEGIN
SET #xml = #customer_xml
SET #xml.modify('
insert <FirstName>{ xs:string(sql:variable("#FirstName")) }</FirstName>
before (/Customer/CustomerData/FirstName)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/FirstName[2]
')
SET #xml.modify('
insert <LastName>{ xs:string(sql:variable("#LastName")) }</LastName>
before (/Customer/CustomerData/LastName)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/LastName[2]
')
SET #xml.modify('
insert <Gender>{ xs:string(sql:variable("#Gender")) }</Gender>
before (/Customer/CustomerData/Gender)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Gender[2]
')
SET #xml.modify('
insert <City>{ xs:string(sql:variable("#City")) }</City>
before (/Customer/CustomerData/Addresses/BillingAddress/City)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Addresses/BillingAddress/City[2]
')
SET #xml.modify('
insert <State>{ xs:string(sql:variable("#State")) }</State>
before (/Customer/CustomerData/Addresses/BillingAddress/State)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Addresses/BillingAddress/State[2]
')
select #xml
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
END
you can also use FLWOR which will allow you to generate the xml in one go by using a template and adding data only to the elements you want.
You won't need to create tables or stored procedures. For example:
declare #x xml
set #x=(select FirstName, LastName from kc_consumer for xml path('CustomerData'))
SELECT #x.query('
for $a in /CustomerData
return
<CustomerData>
<StoreID></StoreID>
<FirstName>{data($a/FirstName)}</FirstName>
<LastName>{data($a/LastName)}</LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
</CustomerData>
')
I'm just including a few nodes for readability, you just need to paste the rest of them.

How to improve this query to avoid hash match

I have q query to select ID of duplicated rows. If the provinceID is same and at least one phonenumber is same, then we can determine that two rows are identicial.
SELECT i1.ID
FROM pigeon.dbo.Instrument i1
WHERE EXISTS(
SELECT i2.ID
FROM pigeon.dbo.Instrument i2
WHERE i2.ID != i1.ID and i2.ProvinceID = i1.ProvinceID and
(
(RTRIM(i2.PhoneNumber1) != '' and (RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber3))) or
(RTRIM(i2.PhoneNumber2) != '' and (RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber3))) or
(RTRIM(i2.PhoneNumber3) != '' and (RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber3)))
)
)
The query excution plan
Whilst the other similar query performs very well, and no hash match in execution plan. The query is
SELECT i1.ID
FROM pigeon.dbo.Instrument i1
WHERE EXISTS(
SELECT i2.ID
FROM pigeon.dbo.Instrument i2
WHERE i2.ID != i1.ID and i2.Name = i1.Name and
(
(RTRIM(i2.PhoneNumber1) != '' and (RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber3))) or
(RTRIM(i2.PhoneNumber2) != '' and (RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber3))) or
(RTRIM(i2.PhoneNumber3) != '' and (RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber3)))
)
)
The execution plan is
I created index for all fields which is included in where clause.
The table is defined as
CREATE TABLE [dbo].[Instrument](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[Gender] [char](1) NULL,
[Birthdate] [datetime] NULL,
[PhoneNumber1] [nvarchar](50) NULL,
[PhoneNumber2] [nvarchar](50) NULL,
[PhoneNumber3] [nvarchar](50) NULL,
[Email] [nvarchar](64) NULL,
[Address] [nvarchar](250) NULL,
[IDType] [smallint] NOT NULL,
[IDNumber] [nchar](32) NULL,
[ProvinceID] [char](16) NOT NULL,
[CityID] [char](16) NOT NULL,
[Blacklist] [bit] NULL,
[BeenProject] [nvarchar](64) NULL,
[BeenCity] [nvarchar](50) NULL,
[BeenDate] [datetime] NULL,
[BeenRemark] [nvarchar](250) NULL,
[PlateType] [smallint] NOT NULL,
[PlateNumber] [nchar](16) NULL,
[Color] [nchar](16) NULL,
[Vendor] [nvarchar](64) NULL,
[ModelID] [bigint] NOT NULL,
[Version] [nvarchar](64) NULL,
[Level] [nvarchar](64) NULL,
[ModelEx] [nvarchar](250) NULL,
[Van] [nvarchar](64) NULL,
[Volume] [nvarchar](64) NULL,
[EngineNumber] [nvarchar](64) NULL,
[VINNumber] [nvarchar](64) NULL,
[ShipmentDate] [datetime] NULL,
[BoughtDate] [datetime] NULL,
[RegisteDate] [datetime] NULL,
[Remark1] [nvarchar](500) NULL,
[Remark2] [nvarchar](500) NULL,
[Remark3] [nvarchar](500) NULL,
[Remark4] [nvarchar](500) NULL,
[Remark5] [nvarchar](500) NULL,
[Referer] [nvarchar](64) NULL,
[Shared] [bit] NOT NULL,
[Counter] [smallint] NOT NULL,
[XRefID] [bigint] NULL,
[Active] [bit] NOT NULL,
[CreatedBy] [nchar](32) NOT NULL,
[CreatedAt] [datetime] NOT NULL,
[UpdatedBy] [nchar](32) NULL,
[UpdatedAt] [datetime] NULL
)
Why their's execution plan is so different? The second query's performance is very good compare to the first query. Please help to improve the performance of the first query.

bulk insert and parse a complex XML file into several tables

I have the following sql stored procedure to bulk insert and parse an xml file and insert its data into several tables in a database.
The sql below works, however its inserting duplicate records into the #questions table and the #cards table.
Any help on this would be much appreciated. Thanks in advance.
Here is the XML file:
<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User>
<UserInfo>
<Id>0001</Id>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>Doejk#net.com</Email>
</UserInfo>
<Questions>
<Question>
<Id>1</Id>
<AnswerId>1</AnswerId>
</Question>
<Question>
<Id>2</Id>
<AnswerId>3</AnswerId>
</Question>
</Questions>
<Cards>
<Card>
<Id>1234</Id>
<Type>Digital</Type>
<Status>Active</Status>
</Card>
<Card>
<Id>1334</Id>
<Type>Physical</Type>
<Status>Not Active</Status>
</Card>
</Cards>
</User>
<User>
<UserInfo>
<Id>0002</Id>
<FirstName>Mary</FirstName>
<LastName>Doe</LastName>
<Email>Doem#net.com</Email>
</UserInfo>
<Questions>
<Question>
<Id>3</Id>
<AnswerId>6</AnswerId>
</Question>
<Question>
<Id>4</Id>
<AnswerId>7</AnswerId>
</Question>
</Questions>
<Cards>
<Card>
<Id>3333</Id>
<Type>Digital</Type>
<Status>Active</Status>
</Card>
<Card>
<Id>4444</Id>
<Type>Physical</Type>
<Status>Active</Status>
</Card>
</Cards>
</User>
</Users>
Here is SQL code
/*************************************************************************
-- CREATE TEMP TABLES --
**************************************************************************/
CREATE TABLE #XMLDATA
(RecordId int IDENTITY(1,1) NOT NULL,
XmlData xml NOT NULL)
CREATE TABLE #USERS
(UserID int null,
firstname varchar(50) null,
lastname varchar(50) null,
email varchar(50) null)
CREATE TABLE #CARDS
(CardId int null,
userid int null,
card_type varchar(50) null,
card_status varchar(50) null)
CREATE TABLE #QUESTIONS
(UserID int null,
Question_ID int null,
Answer_ID int null)
/*************************************************************************
-- LOAD THE WHOLE XML AS SINGLE BLOB --
**************************************************************************/
INSERT INTO #XMLDATA(XmlData)
SELECT *
FROM OPENROWSET(
BULK 'c:\users.xml', SINGLE_BLOB)
/*************************************************************************
-- INSERT USERS --
**************************************************************************/
INSERT INTO #USERS
(userid, firstname, lastname, email)
SELECT href.value('(Id/text())[1]', 'integer'),
href.value('(FirstName/text())[1]', 'varchar(50)'),
href.value('(LastName/text())[1]', 'varchar(50)'),
href.value('(Email/text())[1]', 'varchar(30)'),
FROM #XMLDATA CROSS APPLY
XmlData.nodes('Users') AS userinfo(href)
/*************************************************************************
-- INSERT QUESTIONS INFORMATION --
**************************************************************************/
INSERT INTO #QUESTIONS
(UserId, Question_ID, Answer_ID)
SELECT sref.value('(Id/text())[1]', 'integer'),
qref.value('(Id/text())[1]', 'integer'),
qref.value('(AnswerId/text())[1]', 'integer')
FROM #XMLDATA CROSS APPLY
XmlData.nodes('Users/Questions/Question') AS Ques(qref) CROSS APPLY
XmlData.nodes('Users') AS userinf(sref)
/*************************************************************************
-- INSERT CARD INFORMATION --
**************************************************************************/
INSERT INTO #CARDS
(userid, card_id, card_type,card_status)
SELECT sref.value('(Id/text())[1]', 'integer'),
cref.value('(Id/text())[1]', 'integer'),
cref.value('(Type/text())[1]', 'varchar(50)'),
cref.value('(Status/text())[1]', 'varchar(50)')
FROM #XMLDATA CROSS APPLY
XmlData.nodes('/Users/Cards/Card') AS cardlist(cref) CROSS APPLY
XmlData.nodes('/Users') AS userinf(sref)
I'm not sure what your CROSS JOIN is about.
Here is some shredding.
Tip: Comment out the INSERT portion and just do the SELECT portion until you get those tweaked correctly.
DECLARE #data XML;
SET #data =
N'
<Users>
<User>
<UserInfo>
<Id>0001</Id>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>Doejk#net.com</Email>
</UserInfo>
<Questions>
<Question>
<Id>1</Id>
<AnswerId>1</AnswerId>
</Question>
<Question>
<Id>2</Id>
<AnswerId>3</AnswerId>
</Question>
</Questions>
<Cards>
<Card>
<Id>1234</Id>
<Type>Digital</Type>
<Status>Active</Status>
</Card>
<Card>
<Id>1334</Id>
<Type>Physical</Type>
<Status>Not Active</Status>
</Card>
</Cards>
</User>
<User>
<UserInfo>
<Id>0002</Id>
<FirstName>Mary</FirstName>
<LastName>Doe</LastName>
<Email>Doem#net.com</Email>
</UserInfo>
<Questions>
<Question>
<Id>3</Id>
<AnswerId>6</AnswerId>
</Question>
<Question>
<Id>4</Id>
<AnswerId>7</AnswerId>
</Question>
</Questions>
<Cards>
<Card>
<Id>3333</Id>
<Type>Digital</Type>
<Status>Active</Status>
</Card>
<Card>
<Id>4444</Id>
<Type>Physical</Type>
<Status>Active</Status>
</Card>
</Cards>
</User>
</Users>';
SELECT T.myEntity.value('(Id)[1]', 'VARCHAR(20)')
, T.myEntity.value('(FirstName)[1]', 'VARCHAR(20)')
, T.myEntity.value('(LastName)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Email)[1]', 'VARCHAR(20)')
FROM #data.nodes('Users/User/UserInfo') AS T(myEntity);
SELECT
T.myEntity.value('(../../UserInfo/Id)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Id)[1]', 'INT')
, T.myEntity.value('(AnswerId)[1]', 'INT')
FROM #data.nodes('Users/User/Questions/Question') AS T(myEntity);
SELECT
T.myEntity.value('(../../UserInfo/Id)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Id)[1]', 'INT')
, T.myEntity.value('(Type)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Status)[1]', 'VARCHAR(20)')
FROM #data.nodes('Users/User/Cards/Card') AS T(myEntity);
CREATE TABLE #XMLDATA
(RecordId int IDENTITY(1,1) NOT NULL,
XmlData xml NOT NULL)
CREATE TABLE #USERS
(UserID int null,
firstname varchar(50) null,
lastname varchar(50) null,
email varchar(50) null)