multipart Identifier cound not be bound in stored procedure - stored-procedures

I am creating a procedure. I have an xml file from which i want to update data in my tables. I am creating a procedure to updata data in table.
This is my procedure
Hi,I am creating a procedure. I have an xml file from which i want to update data in my tables. I am creating a procedure to updata data in table.
This is my procedure
CREATE PROCEDURE [dbo].[UpdateAssetsAvailability]
#assetAvailxml xml
BEGIN
SET NOCOUNT ON;
WITH AssetAvail AS
(
SELECT
uniqueKey.value('AssetId[1]', 'nvarchar(255)') as assetid,
uniqueKey.value('AvailabilityStatus[1]', 'nvarchar(255)') as
availabilityStatus,
uniqueKey.value('SourceSystemCode[1]', 'nvarchar(255)') as sscode
FROM
#assetAvailxml.nodes('/Assets/asset') as Keys(uniqueKey)
)
Update dbo.Asset set Availability=(Select Id from dbo.AssetStatus where
Code=AssetAvail.availabilityStatus)
where AssetId=assetid AND SourceSystem=(Select Id from dbo.SourceSystem
where code=AssetAvail.sscode)
END;
This is my XML File
<?xml version="1.0"?>
<Assets>
<asset>
<AssetId>64_assetid</AssetId>
<AvailabilityStatus>Partial</AvailabilityStatus>
<SourceSystemCode>GE_Cares</SourceSystemCode>
</asset>
<asset>
<AssetId>81_assetid</AssetId>
<AvailabilityStatus>Partial</AvailabilityStatus>
<SourceSystemCode>GE_Cares</SourceSystemCode>
</asset>
<asset>
<AssetId>50_assetid</AssetId>
<AvailabilityStatus>Down</AvailabilityStatus>
<SourceSystemCode>GE_Cares</SourceSystemCode>
</asset>
<asset>
<AssetId>1-21B4-4787</AssetId>
<AvailabilityStatus>Up</AvailabilityStatus>
<SourceSystemCode>SIEBEL</SourceSystemCode>
</asset>
</Assets>
</xml>

Did you include ngDialog.js and ngDialog.css to your project?
such as, add following line:
<script src="js/ngDialog.js"></script>
<link href="/css/ngDialog.css" type="text/css">

Related

Can MSXML XPath select attributes? ( UPD: real issue was with default no-prefix namespace )

I want to try parsing Excel XML Spreadsheet file with MSXML and XPath.
https://technet.microsoft.com/en-us/magazine/2006.01.blogtales
https://msdn.microsoft.com/en-us/library/aa140066.aspx
It has a root element of <Workbook xmlns.... xmlns....> and a bunch of next-level nodes <Worksheet ss:Name="xxxx">.
<?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
....
<Worksheet ss:Name="Карточка">
....
</Worksheet>
<Worksheet ss:Name="Баланс">
...
...
...
</Worksheet>
</Workbook>
At a certain step I want to use XPath to get the very names of the worksheets.
NOTE: I do not want the get the names indirectly, that is to select those Worksheet nodes first and then enumerating them manually read their ss:Name child attribute nodes. That I can do, and it is not the topic here.
What I want is to utilize XPath flexibility: to directly fetch those ss:Name nodes without extra indirection layers.
procedure DoParseSheets( FileName: string );
var
rd: IXMLDocument;
ns: IDOMNodeList;
n: IDOMNode;
sel: IDOMNodeSelect;
ms: IXMLDOMDocument2;
ms1: IXMLDOMDocument;
i: integer;
s: string;
begin
rd := TXMLDocument.Create(nil);
rd.LoadFromFile( FileName );
if Supports(rd.DocumentElement.DOMNode,
IDOMNodeSelect, sel) then
begin
ms1 := (rd.DOMDocument as TMSDOMDocument).MSDocument;
if Supports( ms1, IXMLDOMDocument2, ms) then begin
ms.setProperty('SelectionNamespaces',
'xmlns="urn:schemas-microsoft-com:office:spreadsheet" '+
'xmlns:o="urn:schemas-microsoft-com:office:office" '+
'xmlns:x="urn:schemas-microsoft-com:office:excel" '+
'xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"');
ms.setProperty('SelectionLanguage', 'XPath');
end;
// ns := sel.selectNodes('/Workbook/Worksheet/#ss:Name/text()');
// ns := sel.selectNodes('/Workbook/Worksheet/#Name/text()');
ns := sel.selectNodes('/Workbook/Worksheet/#ss:Name');
// ns := sel.selectNodes('/Workbook/Worksheet/#Name');
// ns := sel.selectNodes('/Workbook/Worksheet');
for i := 0 to ns.length - 1 do
begin
n := ns.item[i];
s := n.nodeValue;
ShowMessage(s);
end;
end;
end;
When I use the dumbed down '/Workbook/Worksheet' query MSXML correctly return the nodes. But as soon as I add the attribute to the query - MSXML returns empty set.
Other XPath implementations like XMLPad Pro or http://www.freeformatter.com/xpath-tester.html correctly return the list of ss:Name attribute nodes. But MSXML does not.
What would be the XPath query text to help MSXML return the attribute nodes with given names ?
UPD. #koblik suggested a link to MS.Net selector (not MSXML one) and there are two examples there
https://msdn.microsoft.com/en-us/library/ms256086(v=vs.110).aspx
Example 1: book[#style] - All elements with style attributes, of the current context.
Example 2: book/#style - The style attribute for all elements of the current context.
That is the difference I told in the "NOTE" above: I don't need those books, I need the styles. I need attribute-nodes, not element-nodes!
And that Example 2 syntax is what MSXML seems to fail at.
UPD.2: One tester shows an interesting error claim:
The default (no prefix) Namespace URI for XPath queries is always '' and it cannot be redefined to 'urn:schemas-microsoft-com:office:spreadsheet'
I wonder if that claim about no default namespaces in XPath is really part of standard or just MSXML implementation limitation.
Then if to delete the default NS the results are how they should be:
Variant 1:
Variant 2:
I wonder if that claim about no default namespaces in XPath is really part of standard or just MSXML implementation limitation.
UPD.3: Martin Honnen in comments explains that line: See w3.org/TR/xpath/#node-tests for XPath 1.0 (as supported by Microsoft MSXML), it clearly states "A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null". So in XPath 1.0 a path like "/Workbook/Worksheet" selects elements of that name in no namespace.
UPD.4: So the selection works with '/ss:Workbook/ss:Worksheet/#ss:Name' XPath query, returning "ss:Name" attributes nodes directy. In the source XML document both default (no-prefix) and "ss:" namespaces are bound to the same URI. This URI is acknowledged by the XPath engine. But not the default namespace, which can not be redefined in MSXML XPath engine ( implementing 1.0 specs ). So to make it work, the default namespace should be mapped to another explicit prefix ( either already existing one or a newly created ) via URI and then that substitute prefix would be used in the XPath selection string. Since namespaces matching goes via URI not via prefixes it would not matter if prefixes used in the document and in the query match or not, they would be compared via their URIs.
ms.setProperty('SelectionLanguage', 'XPath');
ms.setProperty('SelectionNamespaces',
'xmlns:AnyPrefix="urn:schemas-microsoft-com:office:spreadsheet"');
and then
ns := sel.selectNodes(
'/AnyPrefix:Workbook/AnyPrefix:Worksheet/#AnyPrefix:Name' );
Thanks to Asbjørn and Martin Honnen for explaining those trivial after-the-fact but not obvious a priori relations.
The issue is that MSXML doesn't support default namespaces when using XPath. To overcome this, you must give the default namespace an explicit prefix, and use this:
ms.setProperty('SelectionNamespaces',
'xmlns:d="urn:schemas-microsoft-com:office:spreadsheet" '+
'xmlns:o="urn:schemas-microsoft-com:office:office" '+
'xmlns:x="urn:schemas-microsoft-com:office:excel" '+
'xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"');
Note how I added the d prefix to the default namespace. Then you can do the selection like this:
ns := sel.selectNodes('/d:Workbook/d:Worksheet/#ss:Name');
The reason this works is that when parsing the XML data, MSXML associates the namespace to each node. At this stage it does handle the default namespace, so the Workbook elements get associated with the urn:schemas-microsoft-com:office:spreadsheet namespace.
However, note that it does not store the namespace prefixes! Thus you can use your own prefixes for the namespaces when you set SelectionNamespaces.
Now, when doing the XPath selection, if the nodes have a namespace you have to specify namespaces for all elements in the XPath, like my example above. And then you use your own prefixes which you set with SelectionNamespaces.

How to reduce XML reading cost in SQL Server 2008 R2

I am reading a xml value and storing in a table but its cost is 82%.
This is my query:
declare #StateNameList XML
set #StateNameList='<StatusList>
<Status>
<StatusName>All</StatusName>
<StatusID>1</StatusID>
</Status>
<Status>
<StatusName>test</StatusName>
<StatusID>2</StatusID>
</Status>
</StatusList>'
SELECT
Table1.Column1.value('(./StatusName)[1]', 'varchar(50)') AS StatusName
FROM
#StateNameList.nodes('/StatusList/Status') AS Table1(Column1)
Please add the below code after from tag then see the execution plan
declare #StateNameList XML
set #StateNameList='<StatusList>
<Status>
<StatusName>All</StatusName>
<StatusID>1</StatusID>
</Status>
<Status>
<StatusName>test</StatusName>
<StatusID>2</StatusID>
</Status>
</StatusList>'
SELECT
Table1.Column1.value('(./StatusName)[1]','varchar(50)') AS StatusName
FROM
#StateNameList.nodes('/StatusList/Status') AS Table1(Column1)
OPTION (OPTIMIZE FOR ( #StateNameList = NULL ))

Transform portion of ETL using Scriptella?

I am trying out Scriptella to see if it will meet my needs. So far, it seems like a great tool. I've spent several hours studying sample scripts, searching forums, and trying to get the hang of nested queries/scripts.
This is an example of my ETL file, slightly cleaned up for brevity. Lines beginning with # are added and not part of the actual ETL file. I am trying to insert/retrieve IDs and then pass them on to later script blocks. The most promising way to do this appears to be using global variables but I'm getting null when trying to retrieve the values. Later, I will be adding code in the scripts blocks that parse and significantly transform fields before adding them into the DB.
There are no errors. I'm just not getting the OS ID and Category IDs that I'd expect. Thank you in advance.
<!DOCTYPE etl SYSTEM "http://scriptella.javaforge.com/dtd/etl.dtd">
<etl>
<connection id="in" driver="csv" url="mycsvfile.csv"/>
<connection id="dest" url="jdbc:mysql://localhost:3306/pvm3" user="user" password="password"/>
<connection id="js" driver="script"/>
<query connection-id="in">
<!-- all columns are selected, notably: OPERATINGSYSTEM, CATEGORY, QID, TITLE -->
<query connection-id="dest">
#Check to see if the OS already exists, and get the ID if it does
select max(os_id) as os_id, count(*) as os_cnt from etl_os where os = ?OPERATINGSYSTEM;
#If it doesnt exist then add it and get the auto_increment value
<script if="os_cnt==0">
insert into etl_os(os) values(?OPERATINGSYSTEM);
<query connection-id="dest">
select last_insert_id() as os_id;
#Store in global so it can be accessed in later script blocks
<script connection-id="js">
etl.globals.put('os_id', os_id);
</script>
</query>
</script>
#Same style select/insert as above for category_id (excluded for brevity)
#See if KB record exists by qid, if not then add it with the OS ID and category ID we got earlier
<query connection-id="dest">
select max(qid) as existing_qid, count(*) as kb_cnt from etl_qids where qid = ?QID
<script if="kb_cnt==0">
insert into etl_qids(qid, category_id, os_id) values (?QID, ?{etl.globals.get('category_id')}, ?{etl.globals.get('os_id')});
</script>
</query>
</query>
</query>
</etl>
Found out how to do it. Essentially, just nest queries to modify the data before passing it to a script. The below is a quick type-up of the solution. I did not understand at first that queries could be immediately nested to transform the row before passing it for processing. My impression was also that only scripts could manipulate the data.
(Query)Raw data -> (Query)manipulate data -> (Script)write new data.
.. in is a CSV file ..
.. js is a driver="script" block ..
<query connection-id="in">
<query connection-id="js">
//transform data as needed here
if (BASE_TYPE == '-') BASE_TYPE = '0';
if (SECONDARY_TYPE == '-') SECONDARY_TYPE = '0';
SIZES = SIZES.toLowerCase();
query.next(); //call nested scripts
<script connection-id="db">
INSERT IGNORE INTO sizes(size) VALUES (?SIZE);
INSERT IGNORE INTO test(base_type,secondary_type) VALUES (?BASE_TYPE, ?SECONDARY_TYPE);
</script>
</query>
</query>

How to call stored procedure from Mule 3.5 with new Database endpoint

I was testing Mule's new Database connector of Mule 3.5 with Stored Procedure ... (Reference :- http://www.mulesoft.org/documentation/display/current/Database+Connector ).. I had a following Stored Procedure :-
ALTER PROCEDURE [dbo].[sp_retrieveData]
#Id int
AS
Select * from getData Where ID = #Id
Which is working fine in Mule's old JDBC connector ... I used to call the stored procedure from the JDBC endpoint using the following syntax :- <jdbc-ee:query key="RetriveQuery" value="CALL sp_retrieveData(${Id})"/> Which worked fine ... But now the issue is in the Mule 3.5 new Database end point I am unable to call the same Stored Procedure ... My Mule configuration is :-
<db:stored-procedure config-ref="Generic_Database_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[CALL sp_retrieveData(58)]]></db:parameterized-query>
<db:in-param name="Id" type="INTEGER" value="58"/>
</db:stored-procedure>
So, My question is how can I call Stored Procedure with the new DB endpoint ... Had anyone tried it ???... Please help ...
Update:-
The following exception I get :-
Exception stack is:
1. The index 1 is out of range. (com.microsoft.sqlserver.jdbc.SQLServerException)
com.microsoft.sqlserver.jdbc.SQLServerException:170 (null)
2. The index 1 is out of range. (com.microsoft.sqlserver.jdbc.SQLServerException). Message payload is of type: String (org.mule.api.MessagingException)
org.mule.module.db.internal.processor.AbstractDbMessageProcessor:81 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
com.microsoft.sqlserver.jdbc.SQLServerException: The index 1 is out of range.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:170)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setterGetParam(SQLServerPreparedStatement.java:698)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setObject(SQLServerPreparedStatement.java:928)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
IMO the best documentation for anything are its tests. The stored procedure tests for the DB module are here: https://github.com/mulesoft/mule/tree/mule-3.5.0/modules/db/src/test/resources/integration/storedprocedure
Based on these, the following should work:
<db:stored-procedure config-ref="Generic_Database_Configuration">
<db:parameterized-query>{ call sp_retrieveData(:Id) }</db:parameterized-query>
<db:in-param name="Id" value="58" />
</db:stored-procedure>
(I haven't tested it though)
Sample Stored procedure call:
<db:stored-procedure config-ref="Oracle_Configuration1" doc:name="Database">
<db:parameterized-query><![CDATA[
{
call apps.create_sales_Order(:p_header_rec_oper, :P_order_number, :P_ordered_date, :P_line_id, :p_flow_Status_code, :P_return_status)
}
]]>
</db:parameterized-query>
<db:in-param name="p_header_rec_oper" value="CREATE"/>
<db:out-param name="P_order_number" type="INTEGER"/>
<db:out-param name="P_ordered_date" type="DATE"/>
<db:out-param name="P_line_id" type="VARCHAR"/>
<db:out-param name="p_flow_Status_code" type="VARCHAR"/>
<db:out-param name="P_return_status" type="VARCHAR"/>
</db:stored-procedure>

Finding elements with XPath in Delphi

I am trying to find an element in an XML document in Delphi. I have this code, but it always says 0 elements in the log:
function TForm1.KannaSidu: Boolean;
var
Doc: IXMLDOMDocument;
List: IXMLDomNodeList;
begin
try
Doc := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument;
Doc.async:=False;
Doc.load(Filename);
except
LogTx('Error on page');
end;
List:=Doc.selectNodes('/html/head');
LogTx(IntToStr(List.length)+' elements');
Result:=False;
end;
So how do I make XPath work?
In the example code I find online for the selectNodes method, it is preceded by code that sets the document's SelectionNamespaces property via setProperty. Some even set SelectionLanguage, too.
Doc.setProperty('SelectionLanguage', 'XPath');
Doc.setProperty('SelectionNamespaces',
'xmlns:xsl=''http://www.w3.org/1999/XSL/Transform''');
Based on the element names you're searching for, I guess you're processing an HTML file. The basic HTML elements are in the http://www.w3.org/1999/xhtml namespace, so try this:
Doc.setProperty('SelectionNamespaces',
'xmlns:x=''http://www.w3.org/1999/xhtml''');
List := Doc.selectNodes('/x:html/x:head');
See also:
selectNodes does not give node list when xmlns is used on Microsoft's forum.
If you're just trying to load a plain html file as xml, it would probably have multiple reasons to fail and choke on things like:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
You have to test that it actually loads correctly before doing anything else:
if not Doc.load(filename) then
raise Exception.Create('XML Loading error:' + Trim(Doc.parseError.reason));
It will give you the specific reason for the failure like this one:
XML Loading error:End tag 'head' does not match the start tag 'link'.
IXMLDOMDocument.Load() does not raise an exception if something goes wrong with your file or with its content. Try the following to be sure there is nothing bad with it:
...
Doc.load(Filename);
if Doc.parseError.errorCode <> 0 then
ShowMessage('Error : ' + + Doc.parseError.reason)
else
ShowMessage('No problem so far !');
...
I suck at XPath but maybe if html is your root node you don't need to include it in your query string, so try the following :
List:=Doc.selectNodes('//html/head');
or
List:=Doc.selectNodes('//head');

Resources