Thursday, May 14, 2009
Great article on XML fields modifications
/* XML Data Modification Language (XML DML) allows you to modify and update XML data. When working with SQL Server Databases, this is the most efficient way to modify elements in an XML column, yet the techniques of using XML-DML have not been well, and simply, described - up until now. Robert Sheldon presents a practical workbench to show the various 'modify' methods (As usual, the source is in the speechbubble above) */
/*
The XML data type - first introduced in SQL Server 2005 and carried over to SQL Server 2008 - brought with it valuable functionality that supports XML documents or their fragments. You can assign the XML data type to columns, variables, or parameters, and you can configure those objects as either typed or untyped. A typed XML column (or variable or parameter) is one that is associated with an XML schema. An untyped column is not.
The XML data type also supports several methods that let you work directly with the XML data. Two common methods are query() and value(). Each one supports XQuery expressions that allow you to retrieve data from the column on which the method is called. However, neither of these methods or the XQuery language let you manipulate the XML data.
For this reason, SQL Server also introduced an extension of XQuery called the XML Data Modification Language (XML DML). You can issue an XML DML query by calling the modify() method supported by the XML data type. In this workbench, I show you several examples of how to manipulate XML data in both typed and untyped XML columns. To support these examples, I created the JobCandidates table in the AdventureWorks database (tested in both SQL Server 2005 and 2008.) The table includes the CandidateResume column, which is a typed XML column, and the CandidateRating column, which is an untyped XML column.
The following set of statements create and populate the table..
*/
USE AdventureWorks;-- Drop JobCandidates table if exists
IF EXISTS(
SELECT table_name FROM information_schema.tables
WHERE table_name = 'JobCandidates')
DROP TABLE JobCandidates;
-- Create JobCandidates table
CREATE TABLE JobCandidates(
CandidateId INT PRIMARY KEY,
-- Create typed XML column
CandidateResume XML
(DOCUMENT HumanResources.HRResumeSchemaCollection) NULL,
-- Create untyped XML column
CandidateRating XML NULL);
-- Insert data into the typed column
INSERT INTO JobCandidates (CandidateId, CandidateResume)
(SELECT JobCandidateId, [Resume]
FROM HumanResources.JobCandidate
WHERE JobCandidateId = 1);
UPDATE JobCandidates
SET CandidateRating =
'
SELECT * FROM JobCandidates;
/*
Notice that the CandidateResume column uses the schema collection named HumanResources.HRResumeSchemaCollection, which is the same collection used by the source data in the HumanResources.JobCandidate table. The CandidateRating column, on the other hand, is not associated with a schema, so I just pass in the simple XML document.
*/
/*
INSERTING DATA INTO AN UNTYPED COLUMN
When you call the modify() method on an XML statement, you must specify whether you are adding, updating, or deleting data. To add data, you must use the 'insert' keyword, followed by the XML data you want to add.
When you insert data into an XML column, you can choose from one of three methods: directly into an element (by using the 'into' keyword), before an element (by using the 'before' keyword), or after an element (by using the 'after' keyword). If you are using the 'into' keyword to insert data into an element that contains child elements, you must specify whether the new element goes before the other elements (by using the 'as first' keywords) or after the other elements (by using the 'as last' keywords). This will all become clearer as you work through the examples.
In the following example, I insert the
In this case, I add that data directly into the first
After specifying the 'into' keyword, you must provide the path of the target element (
In the following example, when I call the
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert
as last
into (/Ratings/Rating[@RatingId="1"])[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
The following results show the XML that is now stored in the CandidateRating column. As you can see, the first
<Ratings>
<Rating RatingId="1">
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
<Communication>2.5Communication>
Rating>
<Rating RatingId="2">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>4.5DbDevelopment>
Rating>
Ratings>
*/
/*
You can achieve the same results as those shown in the previous example by using the 'after' keyword instead of 'insert'. This eliminates the need to include the 'as last' keywords. However, you must define a more complete target path. Notice that in the following example, I've added the
Note that, if you run the following example directly after the preceding example, your
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert
after (/Ratings/Rating[@RatingId="1"]/ToolSkills)[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
You can also define an expression in your insert statement. For example, the following statement includes an if/then/else expression. If the value in the
As you can see below, the example uses the text() function to add text to the
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert
if (/Ratings/Rating[@RatingId="2"]/DbDevelopment > 4)
then text{"This candidate has adequate experience."}
else ()
as first
into (/Ratings/Rating[@RatingId="1"])[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
Because the
<Ratings>
<Rating RatingId="1">
This candidate has adequate experience.
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>4.5DbDevelopment>
Rating>
Ratings>
*/
/*
You can also add two elements at the same time. In the following example, I add both the
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert(
after (/Ratings/Rating[@RatingId="1"]/ToolSkills)[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you can see in the following results, the first
<Ratings>
<Rating RatingId="1">
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
Rating>
<Rating RatingId="2">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>4.5DbDevelopment>
Rating>
Ratings>
*/
/*
In addition to adding elements (or text) to an XML document, you can also add other types of XML nodes, such as comments. In the following example, I add a comment along with the two elements you saw in the previous example. Notice that I include the comment as I would an element. The comment itself follows the conventions of XML comments - enclosed in brackets and the necessary dashes and exclamation mark.
Notice also that the example uses the 'before' keyword instead of 'after'. Now the new elements will be added before the existing child elements.
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert(
,
before (/Ratings/Rating[@RatingId="1"]/AppliedKnowledge)[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you can see the following results, the comment is now included in the XML and is located at the beginning of the set of child elements.
<Ratings>
<Rating RatingId="1">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0.0;/AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>4.5DbDevelopment>
Rating>
Ratings>
*/
/*
In addition to adding elements to an XML document, you can also add attributes to an existing element. To add an attribute, you must include the 'attribute' keyword, followed by the attribute name and its value, which is enclosed in curly brackets. The following example adds the RatingName and RatingType attributes to each
When you add an attribute, you should use the 'insert' keyword. However, you do not need to specify the 'as first' or 'as last' keywords because it does not matter whether there are child elements when you're adding an attribute to the parent element.
Note that the following example, like all the remaining examples in this workbench, build on the preceding examples. This approach helps to demonstrate how to update and delete data, which are described in later sections.
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert(
attribute RatingName {"Skills"},
attribute RatingType {"Scale"})
into (/Ratings/Rating[@RatingId="1"])[1]')
WHERE CandidateId = 1;
UPDATE JobCandidates
SET CandidateRating.modify('
insert(
attribute RatingName {"Qualifications"},
attribute RatingType {"Years"})
into (/Ratings/Rating[@RatingId="2"])[1]')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
The following results from the CandidateRating column show how the two new attributes and their values have been added to each of the
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2" RatingName="Qualifications" RatingType="Years">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>4.5DbDevelopment>
Rating>
Ratings>
*/
/*
UPDATING DATA IN AN UNTYPED COLUMN
As you saw in the previous examples, when you add data to an XML document, you use the 'insert' keyword. However, to update data, you instead use the 'replace value of' keywords. The keywords are followed by the XML path of the element or attribute whose value you want to update. After you specify the path, you then specify the 'with' keyword and the new value.
In the following example, I update the value in the
*/
UPDATE JobCandidates
SET CandidateRating.modify('
replace value of (/Ratings/Rating[@RatingId="2"]/DbDevelopment/text())[1]
with "6.5" ')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As the following results show, the
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating; RatingId="2" RatingName="Qualifications" RatingType="Years">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.5DbDevelopment>
Rating>
Ratings>
*/
/*
If you want to update an attribute's value, you must specify that attribute in the path expression by including it at the end of the path, as shown in the following example. In this case, I am updating the value of the RatingType attribute.
*/
UPDATE JobCandidates
SET CandidateRating.modify('
replace value of (/Ratings/Rating[@RatingId="1"]/@RatingType)[1]
with "Scale 1-5" ')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you can see in the following results, the RatingType attribute of the first
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale 1-5">
<Communication>2.5Communication>
;FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating"> RatingId="2" RatingName="Qualifications" RatingType="Years">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.5DbDevelopment>
Rating>
Ratings>
*/
/*
In the previous two examples, the value defined after the 'with' keyword is a simple string value (enclosed in double quotes). However, you can instead include an expression that defines more complex logic in determining the new value.
For instance, in the following example, I follow the 'with' keyword with an if/then/else expression. To demonstrate how this works, I first add the MeetsMinimum attribute to the second
*/
UPDATE JobCandidates
SET CandidateRating.modify('
insert attribute MeetsMinimum {""}
into (/Ratings/Rating[@RatingId="2"])[1]')
WHERE CandidateId = 1;
UPDATE JobCandidates
SET CandidateRating.modify('
replace value of (/Ratings/Rating[@RatingId="2"]/@MeetsMinimum)[1]
with(
if ((/Ratings/Rating[@RatingId="2"]/Experience)[1] > 8
and (/Ratings/Rating[@RatingId="2"]/DbDevelopment)[1] > 5)
then "Yes"
else "No")')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As the following results show, the MeetsMinimum attribute has been set to Yes because the candidate has the necessary years of experience.
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale 1-5">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2" RatingName="Qualifications" RatingType="Years" MeetsMinimum="Yes">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.5DbDevelopment>
Rating>
Ratings>
*/
/*
DELETING DATA FROM AN UNTYPED COLUMN
Deleting data from an XML column is very straightforward. Simply include the 'delete' keyword in your XML DML expression, followed by the path expression that points to the XML node or attribute you want to delete.
In the following example, I delete the comment in the first
*/
UPDATE JobCandidates
SET CandidateRating.modify('
delete (/Ratings/Rating[@RatingId="1"]/comment()[1])[1]
')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you can see in the following results, the comment has been deleted from the first
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale 1-5">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2" RatingName="Qualifications" RatingType="Years" MeetsMinimum="Yes">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.5DbDevelopment>
Rating>
Ratings>
*/
/*
It is just as easy to delete an attribute. Simply include the attribute name at the end of your path expression, as I've done in the following example. In this case, I'm deleting the MeetsMinimum attribute (created in an earlier example).
*/
UPDATE JobCandidates
SET CandidateRating.modify('
delete (/Ratings/Rating[@RatingId="2"]/@MeetsMinimum)[1]
')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
The following results show that the MeetsMinimum attribute as been deleted from the second
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale 1-5">
<Communication>2.5Communication>
<FormalTraining>4.0FormalTraining>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2" RatingName="Qualifications" RatingType="Years">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.56.5DbDevelopment>
Rating>
Ratings>
*/
/*
To delete an XML element node, define a path expression that points to the element. In the following example, I delete the
*/
UPDATE JobCandidates
SET CandidateRating.modify('
delete (/Ratings/Rating[@RatingId="1"]/FormalTraining)[1]
')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you can see in the following results, the
<Ratings>
<Rating RatingId="1" RatingName="Skills" RatingType="Scale 1-5">
<Communication>2.5Communication>
<AppliedKnowledge>3.0AppliedKnowledge>
<ToolSkills>3.5ToolSkills>
Rating>
<Rating RatingId="2" RatingName="Qualifications" RatingType="Years">
<Experience>9.5Experience>
<Education>16.0Education>
<DbDevelopment>6.5DbDevelopment>
Rating>
Ratings>
*/
/*
INSERTING DATA INTO A TYPED XML COLUMNS
As mentioned earlier, you can use the XML modify() function to update typed or untyped XML data. The examples you've seen so far, have all modified untyped XML. To modify typed XML data, your XML DML expression must also include a namespace declaration. The namespace must match the namespace associated with the XML column, variable, or parameter.
The XML DML expression that modifies typed XML data must include two parts. The first part is the namespace declaration, and the second part is the actual data modification, similar to what you've seen in the preceding examples. The two parts are divided by a semi-colon; however, the entire XML DML expression is still enclosed in one set of single quotes.
In the following example, I use the modify() method to insert a new
After the namespace declaration, I add the semi-colon and then the part of the expression that manipulates the data. This part is similar to what you saw in the previous examples except that each node in the new
by 'ns:', as are the elements listed in the new
When working with typed XML, you can add only those elements and attributes that are supported by the associated schema. If you try to add unsupported elements or attributes, your query will fail.
*/
UPDATE JobCandidates
SET CandidateResume.modify('declare namespace ns=
"http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
insert
before (/ns:Resume/ns:Employment)[1] ')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
The following results show the new
<ns:Employment>
<ns:Emp.StartDate>2006-06-01Z</ns:Emp.StartDate>
<ns:Emp.EndDate>2008-08-30Z</ns:Emp.EndDate>
<ns:Emp.OrgName>Adventure-Works</ns:Emp.OrgName>
<ns:Emp.JobTitle>Apprentice</ns:Emp.JobTitle>
<ns:Emp.Responsibility></ns:Emp.Responsibility>
</ns:Employment>
*/
/*
The process of updating data in a typed XML column is similar to an untyped column. Once again, you must declare the namespace and include the namespace alias in your XML path expressions.
In the following example, I update the
*/
UPDATE JobCandidates
SET CandidateResume.modify('
declare namespace
ns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
replace value of (/ns:Resume/ns:Employment/ns:Emp.Responsibility)[1]
with "Assisting the lead machinist" ')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
The following results show that the new text has been added to the
<ns:Employment>
<ns:Emp.StartDate>2006-06-01Z</ns:Emp.StartDate>
<ns:Emp.EndDate>2008-08-30Z</ns:Emp.EndDate>
<ns:Emp.OrgName>Adventure-Works</ns:Emp.OrgName>
<ns:Emp.JobTitle>Apprentice</ns:Emp.JobTitle>
<ns:Emp.Responsibility>Assisting the lead machinist</ns:Emp.Responsibility>
</ns:Employment>
*/
/*
Deleting data from a typed column is also similar to deleting data from an untyped column. As the following example shows, you must once again declare the namespace and include the namespace alias in each node of your path expression.
*/
UPDATE JobCandidates
SET CandidateResume.modify('
declare namespace
ns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
delete (/ns:Resume/ns:Employment)[1] ')
WHERE CandidateId = 1;
SELECT * FROM JobCandidates;
/*
As you have seen, you can use the XML modify() method to update XML data, whether typed or untyped. The primary difference between the two is that you must reference the schema that is associated with a typed column, variable, or parameter. And any changes you try to make to a typed column must conform to that schema. But once you understand the basic principles of using the modify() method and defining XML DML expressions, you can begin to use the full power of XML DML to manipulate your XML data.
*/
Wednesday, March 18, 2009
Extrime disappointment
GoDaddy accounts do not allow to use ComponentOne services.
This is an extreme disappointment for developers. At the end of a few days exchange with them I came to conclusion that the only possibilities with them to use it is to get Dedicated Server.
Besides that the only dedicated server will work for me is fully dedicated server, which is away too expensive at this time.
Thursday, March 12, 2009
Security Exception
A Day pretty much wasted because of this error...
I did uploaded new testing app for Gulf regional, but Component One did not work.
This works
This doesn't, as I write it.
I sent the questions to Go Daddy, who is a host of this server to change security settings for me and to Component One... So far no luck.
Will see what what is going to happen tomorrow.
The component One Reporting is great. Terrific. Easy and very powerful. Cool looking too. Fast rendering, cashed and so on.
Ingeniously designed. One thing left - make it work on a provider.
This how this page should look like.
Saturday, February 21, 2009
User Authorization on Teach La
Labels: Teach
General Technical Characteristics of TeachLa
More about this site read here.
Teach Louisiana is data base-driven web site. Part of it made on regular ASP(Vb Script) code, all new development are based on ASP.NET (C#). Data back end done in SQL (mostly in 2000) and XML for new development.
New incoming versions for site are going to be Visual Studio 2008 C#, ComponentOne and SQL Server 2008 versions.
Labels: Teach
Friday, February 20, 2009
My guess Department is not going to get this.
This idea is definitely has nothing to do with me. And I do not know what they are talking about. What i am almost certain it is not REALLY a web site.
I heard rumors that somebody requested a Data Warehouse with Web Interface. This is NOT something can be done by a high school student. It is one of the most highest pay job in country. And it is required in a man power. In a high paid man power. Very few people can do that. It is not smart to talk about it by people with no knowledge of the subject.
Department in fact desperately needs something like that, because data are difficult to obtain. Having no data people works like blind and the entire state education is suffering. But it seems to me in this economic climate we will not get anything.
As media starts to do buzz about it - the deal is over and politically dead.
Oh, well. May that means I will still to do some of it and I will have a job. Which is not that bad if you think about it.
Labels: News