SQL Date column in xml - sql

StudentID ExamID 09/05/2017 08/05/2017 07/05/2017 06/05/2017 05/05/2017
123 AS12 12
123 AS13 13 23
While convert the above using "FOR XML PATH , Elements" in sql statement. I got the error.
error:Column name '09/05/2017' contains an invalid XML identifier as
required by FOR XML; '2'(0x0032) is the first character at fault.
Is there any way I will get XML in format:
<row>
<StudentID>123</StockID>
<LessonID>AS13</LessonID>
<09/05/2017>13</09/05/2017>
<08/05/2017>23</08/05/2017>
<07/05/2017></07/05/2017>
<06/05/2017></06/05/2017>
<05/05/2017></05/05/2017>
</row>

It is a very bad design, to store your date-based values in columns of the student table. Whenever you have to add a column in order to add more data, the design is bad... This should be stored in a related side table, while a PIVOT query constructs this output format, whenever you need it.
And: Avoid culture specific date formats!!!
How should one know, wheter 06/05/2017 is the 6th of May or the 5th of June? Use ISO8601 like 2017-05-06 (which makes it sure, that you think about the 6th of May)
About your question: No, this is impossible!
XML does not allow an element's name like '05/05/2017'. You must start with a non-numeric character or an underscore and several characters like the / are forbidden...
Try to create your XML similar to
<row>
<StudentID>123</StockID>
<LessonID>AS13</LessonID>
<Marks>
<Mark date="2017-05-09">13<Mark>
<Mark date="2017-05-08">23<Mark>
[... more of them ...]
</Marks>
</row>

This error goes back to how to treat strings in the language you wish to program in. In this case once you are inside the brackets(<>) the slash is (/) is a special character and the first set of algorithms that process this (regex) XML identify the slash as an issue thereby throwing the error.
Additionally you may want to consider how you want to treat your objects in XML. First group is the class, the class has many students, and the students take many lessons, and each lesson has a grade. (or in this case it looks like a lesson has many grades, not shown here)
<CLASS>
<STUDENT>
<StudentID>123</StudentID>
<LESSON>
<LessonID>AS12</LessonID>
<DATE>09/05/2017</DATE>
<GRADE>93.00</GRADE>
</LESSON>
<LESSON>
<LessonID>AS12</LessonID>
<DATE>08/05/2017</DATE>
<GRADE>93.00</GRADE>
</LESSON>
</STUDENT>
<STUDENT>
...
</STUDENT>
</CLASS>

Related

Optaplanner: Howto change the sample XML in the nurserostering demo?

I am stucked with the Nurserostering example in Optaplanner. I would like to change the input XML to play around (for example increase the number of nurses from 30 to 100), and I find it's very complicated to manually edit it, so I think there must be some kind of 'generator', or maybe I should make my own 'XML generator'.
For example I see every node in the sample has a unique id, so if I want to increase the number of nurses, it's not as simple as copying the last Employee node and pasting it 70 times; I should check every id inside and increase it accordingly.
<Employee id="358">
<id>6</id>
<code>6</code>
<name>6</name>
<contract reference="36"/>
<dayOffRequestMap id="359">
<entry>
<ShiftDate reference="183"/>
<DayOffRequest id="360">
<id>18</id>
<employee reference="358"/>
<shiftDate reference="183"/>
<weight>1</weight>
</DayOffRequest>
...
Therefore, I ask, is there any method to generate this (or other) XML?
The best way I could think of is write a small java application where you could load the original dataset, and then add any number of employees you want (using java code of course). At least this is what I do when I need a bigger dataset or when I toy around the model data (because the dataset need to be updated too).
Oh I almost forgot, sometimes I use xml viewer to help me do some manual copy and paste work (it help me a lot since the row is thousand lines).
You looked at the wrong XML file! Instead of taking e.g. data/nurserostering/unsolved/medium01.xml, take data/nurserostering/import/medium01.xml.
<Employees>
<Employee ID="0">
<ContractID>0</ContractID>
<Name>0</Name>
<Skills>
<Skill>Nurse</Skill>
</Skills><
</Employee>
[...]
<DayOffRequests>
<DayOff weight="1">
<EmployeeID>0</EmployeeID>
<Date>2010-01-21</Date>
</DayOff>
[...]
This file can then easily be edited and imported in OptaPlanner.

Field value query with special character and unfiltered search returning unexpected results?

Field value query is giving unexpected results when any special character(#,=,#,$,%,^,*) is passed.
please find the 4 sample docs I have inserted in to ML.
<root>
<journalTitle>Dinesh</journalTitle>
<sourceType>JA</sourceType>
<title>title1</title>
<volume>volume0</volume>
</root>
<root>
<journalTitle>Gayari</journalTitle>
<sourceType>JA</sourceType>
<title>title1</title>
<volume>volume0</volume>
</root>
<root>
<journalTitle>Dixit</journalTitle>
<sourceType>JA</sourceType>
<title>title1</title>
<volume>volume0</volume>
</root>
<root>
<journalTitle>Singla</journalTitle>
<sourceType>JA</sourceType>
<title>title1</title>
<volume>volume0</volume>
</root>
CTS Query :
cts:search(
fn:doc(),
cts:field-value-query("Sample","######*()", ("unwildcarded")),
"unfiltered"
)
On running this query I am getting all the documents.
As per my understanding, it should return an empty sequence.
please find below the field I have created.
Field (in XML format) :
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://marklogic.com/xdmp/database">
<field-name>Sample</field-name>
<field-path>
<path>/root/journalTitle</path>
<weight>1.0</weight>
</field-path>
<word-lexicons/>
<included-elements/>
<excluded-elements/>
<tokenizer-overrides/>
</field>
Index setting:
If I will add any alphabet(s) in the search string it will give me the correct results.
Like:
##$%F
=====S
df===$d
Please help me to resolve this issue?
Try passing "exact" as an option to cts:field-value-query:
cts:search(
fn:doc(),
cts:field-value-query("Sample","######*()", ("exact")),
"unfiltered"
)
MarkLogic has an index for exact values to help in cases like this. Note it's only on when you have both case sensitive and diacritic sensitive indexes enabled (which you do). I know this works for cts:element-value-query so I expect it will for cts:field-value-query as well.
Use instead the 'exact' option in the field-value-query.
This requires the fast diacritic- and case-sensitive options, but you already have those enabled.
You can also try xdmp:plan before and after using 'exact' to see the effect on the query plan.
In the 'tokenizer overrides' option for your field, add these special character(#,=,#,$,%,^,*) as words (select 'word').
These special characters are not considered for matching by default. You need to override the default tokenizer to include them as words.
May I know what output are you expecting on passing this cts:element-word-query(xs:QName("journalTitle"),"=====S") for the above given for xmls.
Changing the one character searches to true in database config, resolves the issue in element-word-query.

FOR XML PATH in SQL server and [text()]

I found some article on internet
this url
Then I code query like that and I get same result
But when I change AS [text()] to [name]
the result contain XML tag
like this
So My question is What is [text()] in this code
Thank you.
The other current answers don't explain much about where this is coming from, or just offer links to poorly formatted sites and don't really answer the question.
In many answers around the web for grouping strings there are the copy paste answers without a lot of explanation of what's going on. I wanted to better answer this question because I was wondering the same thing, and also give insight into what is actually happening overall.
tldr;
In short, this is syntax to help transform the XML output when using FOR XML PATH which uses column names (or aliases) to structure the output. If you name your column text() the data will be represented as text within the root tag.
<row>
My record's data
<row>
In the examples you see online for how to group strings and concat with , it may not be obvious (except for the fact that your query has that little for xml part) that you are actually building an XML file with a specific structure (or rather, lack of structure) by using FOR XML PATH (''). The ('') is removing the root xml tags, and just spitting out the data.
The deal with AS [text()]
As usual, AS is acting to name or rename the column alias. In this example, you are aliasing this column as [text()]. The []s are simply SQL Server's standard column delimiters, often unneeded, except today since our column name has ()s. That leaves us with text() for our column name.
Controlling the XML Structure with Column Names
When you are using FOR XML PATH you are outputting an XML file and can control the structure with your column names. A detailed list of options can be found here: https://msdn.microsoft.com/en-us/library/ms189885.aspx
An example includes starting your column name with an # sign, such as:
SELECT color as '#color', name
FROM #favorite_colors
FOR XML PATH
This would move this column's data to an attribute of the current xml row, as opposed to an item within it. You end up with
<row color="red">
<name>tim</name>
</row>
<row color="blue">
<name>that guy</name>
</row>
So then, back to [text()]. This is actually specifying an XPath Node Test. In the context of MS Sql Server, you can learn about this designation here. Basically it helps determine the type of element we are adding this data to, such as a normal node (default), an xml comment, or in this example, some text within the tag.
An example using a few moves to structure the output
SELECT
color as [#color]
,'Some info about ' + name AS [text()]
,name + ' likes ' + color AS [comment()]
,name
,name + ' has some ' + color + ' things' AS [info/text()]
FROM #favorite_colors
FOR XML PATH
Notice we are using a few designations in our column names:
#color: a tag attribute
text(): some text for this root tag
comment(): an xml comment
info/text(): some text in a specific xml tag, <info>
The output looks like this:
<row color="red">
Some info about tim
<!--tim likes red-->
<name>tim</name>
<info>tim has some red things</info>
</row>
<row color="blue">
Some info about that guy
<!--that guy likes blue-->
<name>that guy</name>
<info>that guy has some blue things</info>
</row>
Wrapping it up, how can these tools group and concat strings?
So, with the solutions we see for grouping strings together using FOR XML PATH, there are two key components.
AS [text()]: Writes the data as text, instead of wrapping it in a tag
FOR XML PATH (''): Renames the root tag to '', or rather, removes it entirely
This gives us "XML" (air quotes) output that is essentially just a string.
SELECT name + ', ' AS [text()] -- no 'name' tags
FROM #favorite_colors
FOR XML PATH ('') -- no root tag
returns
tim, that guy,
From there, it's just a matter of joining that data back to the larger dataset from which it came.
While righting the sql query remove alias name then you got the text.
select name+',' aa from employee for xml path('')
then the result comes in xml with aa tag.
select (select name+',' from employee for xml path('')) aa

SQL and escaped XML data

I have a table with a mix of escaped and non-escaped XML. Of course, the data I need is escaped. For example, I have:
<Root>
<InternalData>
<Node>
<ArrayOfComment>
<Comment&gt
<SequenceNo>1</SequenceNo>
<IsDeleted>false</IsDeleted>
<TakenByCode>397</TakenByCode>
</Comment&gt
</ArrayOfComment>
</Node>
</InternalData>
</Root>
As you can see, the data in the Node tag is all escaped. I can use a query to obtain the Node data, but how can I convert it to XML in SQL so that it can be parsed and broken up? I'm pretty new to using XML in SQL, and I can't seem to find any examples of this.
Thanks
You have not given enough information about your end goal, but this will get you very close. FYI - You had two missing ; both after comment&gt
declare #xml xml
set #xml = '
<Root>
<InternalData>
<Node>
<ArrayOfComment>
<Comment>
<SequenceNo>1</SequenceNo>
<IsDeleted>false</IsDeleted>
<TakenByCode>397</TakenByCode>
</Comment>
</ArrayOfComment>
</Node>
</InternalData>
</Root>
'
select convert(xml, n.c.value('.', 'varchar(max)'))
from #xml.nodes('Root/InternalData/Node/text()') n(c)
Output
<ArrayOfComment>
<Comment>
<SequenceNo>1</SequenceNo>
<IsDeleted>false</IsDeleted>
<TakenByCode>397</TakenByCode>
</Comment>
</ArrayOfComment>
The result is an XML column that you can put into a variable or cross-apply into directly to get data from the XML fragment.
Your best bet might be to look into a HTML Decoding UDF. I did a quick search and found this one:
http://www.andreabertolotto.net/Articles/HTMLDecodeUDF.aspx
You may want to modify it so it only decodes > and <. The one above seems to go above and beyond your needs.
UPDATE
#Cyberkiwi's solution seems to be a bit cleaner. I will leave this up in case the version of SQL Server you are running doesn't support his solution.

How to get required XML element from not well formed XML data in SQL server

In my SQL 2008 database table, I have one column name AUTHOR that contains XML data. The XML is not well formed and has data like below
<Author>
<ID>172-32-1176</ID>
<LastName>White</LastName>
<FirstName>Johnson</FirstName>
<Address>
<Street>10932 Bigge Rd.</Street>
<City>Menlo Park</City>
<State>CA</State>
</Address>
</Author>
Some XML have all of above data and some have just one tag.
<ID>172-32-1176</ID>
I want to write query that returns me a column as identiry.
I tried using AUTHOR.query('data(/Author/ID)') as identity but it fails when XML does not have Author node.
Thanks,
Vijay
Have you tried something like /Author/ID|/ID ? i.e. try for the first scenario, and with no match, the second ?
(note that the | operator is a set union operator, as described here)
In case that nothing "certain" can be maintained about the XML, except that a unique ID element contains the required identity value, then the following XPath expression selects the ID element:
//ID