RC0 SQL Server 2008 for some reason seems to be quietly done, didn't realise it was out, it is available to download at SQL Server 2008 RC
PS: SQL Server 2008 RC0 will automatically expire after 180 days
RC0 SQL Server 2008 for some reason seems to be quietly done, didn't realise it was out, it is available to download at SQL Server 2008 RC
PS: SQL Server 2008 RC0 will automatically expire after 180 days
In SQL Server 2000 we were limited by the 32 level recursion limit for TSQL, and storing and querying hierarchical data in the form of trees was really difficult and inefficient, We used Cursors or temporary tables to write these queries. But simplicity, maintenance or performances were sacrificed. Ofcourse we could bundle a bit of code in the data layer of your application to share the load however this didn't the solve the problem in reporting scenarios where the data processing was to be done on the database server
As we moved on to SQL Server 2005 it improved because of the introduction of CTE's, CTE's where beautiful solutions to solving querying hierarchical data, I use the word beautiful because it looked nicer on the outset when you used it without knowing the limitations it worked well on development environments For e.g using the AdventureWorks database we could use a CTE to query employee manager data as shown below
WITH UpperHierarchy(EmployeeId, LastName, Manager, HierarchyOrder) AS ( SELECT emp.EmployeeId, emp.LoginId, emp.LoginId, 1 AS HierarchyOrder FROM HumanResources.Employee AS emp WHERE emp.ManagerId isNull UNION ALL SELECT emp.EmployeeId, emp.LoginId, Parent.LastName, HierarchyOrder + 1 FROM HumanResources.Employee AS emp INNER JOIN UpperHierarchy AS Parent ON emp.ManagerId = parent.EmployeeId ) SELECT * From UpperHierarchy
Although this decreased the complexity of writing queries, performance of these queries was still challenged on large databases, the optimisation of the CTE execution plans did improve things but as in any database situation the optimizer is handicapped without indexing capabilities. Indexes reduce the load on the query increasing performance and scalability. In addition in SQL 2005 the underlying storage structure was still something users had to design to suit there requirements. This just got better with the introduction of a new managed SQL CLR data type called HeirarchyID in SQL Server 2008., It is available ready to use in the databarse server now... If you now look back and remember the introduction of the CLR into SQL Server in Yukon you will appreciate this feature even more and how it has been panned out..
This data type does not store the identifier of the parent element but a set of information to locate the element in the hierarchy. This type represents a node in the tree structure. If you look at values contained in a column of HeirarchyID type, you realize that they are binary values.It is extremely compact and supports arbitrary inserts and deletions. As per MS a node in an organizational hierarchy of 100,000 people with an average fanout of 6 levels takes about 38 bits. This is rounded up to 40 bits, or 5 bytes, for storage. Because it stores the elements hierarchy in its entirety it is also indexable now..
As always there are a few limitations
We can represent the HeirarchyID type in a string format. This format shows clearly information carried by this type. Indeed, string representation is formatted as is:/<index level 1>/<index level 2>/…/<index level N>. This representation corresponds to atree structure . Note that first child of a node does not have a value of 1 all the time but can have the /1.2/ value. So to play around a bit we first need a table with a column of HeirarchyID type and an index on the hierarchy ID column
CREATE TABLE Organization ( EmployeeID heirarchyid NOT NULL, EmployeeName nvarchar(50) NOT NULL ) ALTER TABLE dbo.Organization ADD HierarchyLevel As EmployeeID.GetLevel() CREATE INDEX IX_Employee ON Organization(HierarchyLevel,EmployeeID);
To populate the data table we use the CTE we mentioned earlier to just modify the SELECT statement like the following
Insert Into dbo.Organization(EmployeeId, EmployeeName) Select Node, LastName From UpperHierarchy
Now Hierarchical data can be queried using the functions
HeirarchyID data type can be manipulated through a set of functions.· GetAncestor, GetDescendant, GetLevel, GetRoot, ToString, IsDescendant, Parse, Read, Reparent, Write, for details on the functions please refer to the CTP documentation of Katmai but most of them are self explanatory #
For e.g to see how we use these functions, let us insert a node as the last child of an existing node.To do this we first retrieve the sibling node.
--finding sibling node SELECT @sibling = Max(EmployeeID) FROM dbo.Organization WHERE EmployeeId.GetAncestor(1)= @Parent; --inserting node INSERT dbo.Organization(EmployeeId, EmployeeName) VALUES(@Parent.GetDescendant(@sibling,NULL), @Name)
We do not always want to (or can) recover the sibling node to perform insertion. There is perhaps an implied policy to determine node position. For example, let’s say we have an [order] column which position nodes among its siblings. We can compute node path as string: In this example, since the node @Parent is the root, that will give/<order>/. Thanks to the Parse() function, we can use this value to create the new node.
Declare @Parent As HeirarchyID = HeirarchyID::GetRoot() Declare @NewPath As varchar(10)= @Parent.ToString()+ CAST([Order] AS varchar(3))+ '/' INSERT dbo.Organization(EmployeeId, EmployeeName) VALUES(HierarchyId::Parse(@NewPath),'aChild')
You will have note the new syntax of SQL Server 2008 to declare and assign variables in only one line. :: denotes a static method on a SQL CLR type in TSQL. So what am i getting to finally the CTE is not so much of a beauty anymore, just run this query to see what it returns
Select * From dbo.Organization Where @BossNode.IsDescendant(EmployeeId)
If you run this query along side the CTE query and compare the execution plan of these queries you would see why this new feature is being talked about :)
In SQL 2008 some new row value constructors have been added, we are familiar with the INSERT statement which has been around for ages the ANSI way
INSERT INTO Table1 (column1 ,column2 ,... columnN) VALUES (value1,value2,....valueN)
Another way of inserting a single row of data is as follows
INSERT INTO Table1 SELECT value1,value2,....valueN
Similarly for multiple rows of data
INSERT INTO Table1 SELECT value1,value2,....valueN UNION SELECT value1,value2,....valueN UNION SELECT value1,value2,....valueN
Now the new ROW VALUE CONSTRUCTOR allows the following to add multiple rows of data
INSERT INTO Table1(column1 ,column2 ,... columnN) VALUES (value1 , value2 , ... valueN), (value1 , value2 , ... valueN), (value1 , value2 , ... valueN), (value1 , value2 , ... valueN), (value1 , value2 , ... valueN),
We normally use INSERT statements in stored procedures using parameters to the stored procedure, so the above row value constructor is not very useful , it seems to be use of a table valued parameter to insert multiple rows of data is a better option in SQL Server 2008
Database is a form of software development and yet all too often the database is thought of as a secondary entity when development teams discuss architecture and test plans—many developers do not seem to believe, understand or leave alone feel the need to understand that standard software development best practices apply to database development. Virtually every application imaginable requires some form of data store. And many in the development community go beyond simply persisting data, creating applications that are data driven. Given this dependency upon data and databases, Data is the central factor that dictates the value any application can bring to its users. Without the data, there is no need for the application.
The very reason we use the word legacy to refer to an application as old as 3 years is more often than not because of the database. As applications grow in size with new features , the amount of thought put into refactoring front end code or developing new code by developers is not put into the database development, ,so what happens essentially is a situation where your front end is two years ahead of the database , and as time progresses your applications capabilities and features get pulled back by the limitations of database quality and standard. We can all deny this but in reality it results either in a limitation or extra cost on creating work arounds.
The central argument on many a database forum is what to do with that ever-present required logic. Sadly, try as we might, developers have still not figured out how to develop an application without the need to implement business requirements. And so the debate rages on. Does “business logic” belong in the database? In the application tier? What about the user interface? And what impact do newer application architectures have on this age-old question?In recent times I have been able to have a look at technologies like Astoria, Linq and the Entity Model framework and Katmai. I was amazed at how little or no database code needs to be written by a developer who is doing UI or business layer development in a software. At the same time being a SQL Server fan myself.. I was worried that my database skills will slowly vaporise into thin air. Hmm that's not as bad as it sounds. All these new technologies such as Astoria, Linq or the Entity Framework are abstractions of the database and allow developing a logical data layer which maps to a physical database , so all developers who work primarily in the UI level or business layer level will slowly stop doing any SQL code at all, instead churning code that interests them against a logical data layer, but what contradicts this is the need to learn a new syntax in the form Linq, . On the other hand, database development will shift to being the specialist job...the design development and management activities of the database developer and Administrator will begin emerging as specialist skills as opposed to generalist skills in the near future. The future of the database specialist seems to be bright.. but what is to be seen is how organisations look at this shift in software development ideology.. To be fair this model of specialist and generalists is not new..
We sure have used Group By in our SQL queries to group data and get result sets with aggregates from SQL Server, But before I explain lets create a temporary table with order details table using the Northwind database in SQL 2000
I will just join orders and [order detail] table in Northwind to get the data i need into a temporary table as shown below
SELECT O.OrderID, ProductID, UnitPrice, Quantity, (UnitPrice*Quantity) AS Amount, CustomerID INTO #tempOrders FROM Orders O INNER JOIN [order details] D ON O.[orderid] = D.[orderid] ORDER BY ProductID
So now i have a table called #tempOrders with the order details i need.
Now suppose I'd like to see the customers that were sold Product #1 along with the total amount that they spent. I will usea query with a GROUP BY clause as below with a WHERE condition to filter records
SELECT CustomerID, SUM(Amount) AS TotalAmount FROM #tempOrders WHERE ProductID = 1 GROUP BY CustomerID
Now, let's say that I'd like to see all customers that have been sold any products, but we still just want to see the "TotalAmount" for ProductID #1. For customers that have never ordered ProductID #1, it should output a "TotalAmount" value of 0. One way to do this is with a CASE expression as shown below
SELECT CustomerID, SUM(CASE WHEN ProductID = 1 THEN Amount ELSE 0 END) AS TotalAmount FROM #tempOrders GROUP BY CustomerID
Now this would return customers who haven't purchased Product #1 with a total of 0. In situations like these the SUM(CASE...) expression can be replaced with a GROUP BY ALL.
SELECT CustomerID, ISNULL(SUM(Amount), 0) AS TotalAmount FROM #tempOrders WHERE ProductID = 1 GROUP BY ALL CustomerID
Values that are excluded from the aggregation according to the WHERE clause have NULL values returned, the ISNULL function makes sure all customers who haven't ordered Product #1 have a total of 0 instead of NULL. The ALL option basically says "ignore the WHERE clause when doing the GROUPING, but still apply it for any aggregate functions". So, in this case, the WHERE clause is not considered when generating the population of CustomerID values, but it is applied when calculating the SUM. This is very much like our first solution, where we removed the WHERE clause completely, and used a SUM(CASE...) expression to conditionally calculate the aggregate.
GROUP BY ALL is kind of obscure and neat to know, but not really useful in most situations since there are usually easier or better ways to get this result. This won't work if we want all Customers to be displayed, since a customer must have at least one order to show up in the result.Another limitation is we can not use GROUP BY ALL if we want to return a grand total for all orders
There may be situations while writing SQL code where we would like to have totals or aggregates of columns alongside a column, e.g number of points scored by a sales person with their sales, as well as separate sales by month or year.
So lets first create a table which represents sales data as below
CREATE TABLE #tempTest
(
empName VARCHAR(25),
noOfSales INT,
[monthName] VARCHAR(3),
Points INT
)
Just add a few rows of data to this table
INSERT INTO #tempTest VALUES('James',2,'Jan', 2);
INSERT INTO #tempTest VALUES('Jason',1,'Jan', 1);
INSERT INTO #tempTest VALUES('Mark',3,'Jan', 3);
INSERT INTO #tempTest VALUES('Mark',1,'Jan', 1);
INSERT INTO #tempTest VALUES('James',1,'Feb', 1);
INSERT INTO #tempTest VALUES('James',2,'Feb', 2);
INSERT INTO #tempTest VALUES('Jason',3,'Feb', 3);
INSERT INTO #tempTest VALUES('Jason',2,'Feb', 2);
INSERT INTO #tempTest VALUES('Mark',1,'Mar', 1);
INSERT INTO #tempTest VALUES('James',2,'Mar', 2);
INSERT INTO #tempTest VALUES('Jason',2,'Mar', 2);
Now to show how many sales each sales person gets per month we could use PIVOT to achieve this easily
SELECT
empName,
[Jan] AS Total_Sales_Jan,
[Feb] AS Total_Sales_Feb,
[Mar] AS Total_Sales_Mar
FROM
(
SELECT
empName, noOfSales, [monthName]
FROM
#tempTest
) AS Source PIVOT (SUM(noOfSales) for [monthName] IN ([Jan],[Feb],[Mar]) )AS PivotTable
This query results in the following result
Please note that PIVOT can have only one non pivoted column, Example below shows how PIVOT can be used incorrectly
SELECT
empName,
SUM([Jan]) AS Jan,
SUM([Feb]) AS Feb,
SUM([Mar]) AS Mar,
SUM(Points) AS Points
FROM
(
SELECT
empName,
noOfSales,
[monthName],
Points
FROM
#tempTest
) AS Source PIVOT (SUM(noOfSales) for [monthName] IN ([Jan],[Feb],[Mar]) )AS PivotTable
GROUP BY
empName
Note that the results are incorrect for Points, they dont sum up correctly for each sales person as expected, this is because you cannot use more than one unpivoted column
UNPIVOT is the exact opposite of PIVOT although the usage of it is likely to be minimal there are chances this may be used in some occassions
As the integration of geospatial information into applications becomes more prevalent, we will require database systems that can store and manipulate spatial data. With the introduction of the spatial types, SQL Server 2008 provides a data storage solution for spatial data, and enables organizations of any scale to integrate geospatial features into their applications and services.
For the last three weeks i have been playing around with SQL Server 2008 (Katmai) CTP. I managed to install it on Windows 2003 server without any problems. Although i would advise people not to install alongside SQL Server 2005. If you want to use management studio of SQL 2008 CTP be sure to use the developer edition CTP, the expression edition only comes with some client tools. Since its a CTP and you only are trying to get your head around new features it is useful to have management studio installedAs with any CTP i didnt know where to start and i found that Chad Boyd ihas listed the new features for Katmai quite extensively on his blog. Since I am just a developer and i filtered the list of features that may be more useful for a developer to look at.. I m planning to plough through one feature at a time and put up some information on this site for people who are interested.
Performance
Management
Development Enhancements
Service Broker
Data Storage
Reporting