<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Piotr Rodak : partitioned views</title><link>http://sqlblog.com/blogs/piotr_rodak/archive/tags/partitioned+views/default.aspx</link><description>Tags: partitioned views</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Partitioned views</title><link>http://sqlblog.com/blogs/piotr_rodak/archive/2010/09/11/partitioned-views.aspx</link><pubDate>Sat, 11 Sep 2010 00:27:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28689</guid><dc:creator>Piotr Rodak</dc:creator><slash:comments>1</slash:comments><comments>http://sqlblog.com/blogs/piotr_rodak/comments/28689.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/piotr_rodak/commentrss.aspx?PostID=28689</wfw:commentRss><description>&lt;p&gt;I must say I am a big fan of views. They give flexibility of changing the logic of the data retrieval without affecting DAL layers in your application. I posted series of articles about &lt;a href="http://usepubs.blogspot.com/2010/06/updateable-views-how-to-use-them.html"&gt;updateable views&lt;/a&gt; and &lt;a href="http://usepubs.blogspot.com/2010/06/instead-of-triggers-on-views.html"&gt;triggers on views&lt;/a&gt;, their &lt;a href="http://usepubs.blogspot.com/2010/07/instead-of-triggers-using-views-in-ssis.html"&gt;application in SSIS&lt;/a&gt; for example.&lt;/p&gt;  &lt;p&gt;Recently we finished development of system that loads data from several external sources, makes some calculations on the data and sends data over FTP to downstream systems. I designed the whole data interface to use views and stored procedures. This way, even though we used ORM to perform some of the activities, it was not accessing bare tables. This is good, because you can implement simpler and more flexible security model. The other advantage is that you if you use some simple techniques, you can load data to table and then expose the new data through a view without exposing the logic to the upper layers of your application.&lt;/p&gt;  &lt;p&gt;It is quite common requirement to be able to maintain multiple versions of data within table. The requirement is also that data import should not affect other processes which read current version of data. With views it is really simple to achieve. There are many ways of doing this, but let’s have a look at partitioned views technique.&lt;/p&gt;  &lt;p&gt;Partitioned view is a view that selects data from more than one table. These tables have to follow specific requirements. Amongst the other, there has to be so called partitioning column defined, which has trusted CHECK constraint defined on it. The tables have to be joined by UNION ALL operator. If you want the view to be updateable, the partitioning column has to be part of the primary key of all tables belonging to the view. And you have to select all columns from the table.&lt;/p&gt;  &lt;p&gt;OK, but what is the purpose of creating partitioned views? The short answer is performance. Tables tend to grow bigger and bigger. It becomes more and more expensive to run index updates, backups, and queries against them. If you are able to partition your data and you do it in a right way, you can alleviate some of the issues related to big tables. Classic example would be partitioning by date – you can keep month worth of data in each table and span the view over 12 tables to cover the whole year. Nice thing about partitioned views is that you can index underlying tables in a different way, so for example history tables have more indexes allowing for faster data retrieval, while current month table can be optimized for faster inserts and updates.&lt;/p&gt;  &lt;p&gt;Let’s have a look at this scenario. I will use as an example table Sales.CurrencyRate from AdventureWorks database. This table contains 13532 rows in my database, but let’s imagine we have 135 million rows.&lt;/p&gt;  &lt;p&gt;When I run this query, I get 37 rows spanning years 2001 - 2004:&lt;/p&gt;  &lt;div id="codeSnippetWrapper" style="border:1px solid silver;padding:4px;font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;   &lt;div id="codeSnippet" style="padding:0px;font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;     &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; &lt;span&gt;count&lt;/span&gt;(*) NumberOfRates, &lt;span&gt;Year&lt;/span&gt;([CurrencyRateDate]) RateYear, &lt;span&gt;Month&lt;/span&gt;([CurrencyRateDate]) RateMonth &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt; &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate    &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt; &lt;span&gt;group&lt;/span&gt; &lt;span&gt;by&lt;/span&gt; &lt;span&gt;Year&lt;/span&gt;([CurrencyRateDate]), &lt;span&gt;Month&lt;/span&gt;([CurrencyRateDate])   &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt; &lt;span&gt;order&lt;/span&gt; &lt;span&gt;by&lt;/span&gt; RateYear, RateMonth&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;We will create four tables, each for each year that is represented by CurrencyRateDate column.&lt;/p&gt;

&lt;p&gt;A slightly abbreviated DDL for the Sales.CurrencyRate table is as follows:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="border:1px solid silver;padding:4px;font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
  &lt;div id="codeSnippet" style="padding:0px;font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; &lt;span&gt;CREATE&lt;/span&gt; &lt;span&gt;TABLE&lt;/span&gt; [Sales].[CurrencyRate](&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt;     [CurrencyRateID] [&lt;span&gt;int&lt;/span&gt;] &lt;span&gt;IDENTITY&lt;/span&gt;(1,1) &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt;     [CurrencyRateDate] [datetime] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt;     [FromCurrencyCode] [&lt;span&gt;nchar&lt;/span&gt;](3) &lt;span&gt;COLLATE&lt;/span&gt; Latin1_General_CI_AS &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt;     [ToCurrencyCode] [&lt;span&gt;nchar&lt;/span&gt;](3) &lt;span&gt;COLLATE&lt;/span&gt; Latin1_General_CI_AS &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt;     [AverageRate] [money] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt;     [EndOfDayRate] [money] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt;     [ModifiedDate] [datetime] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt; &lt;span&gt;CONSTRAINT&lt;/span&gt; [DF_CurrencyRate_ModifiedDate]  &lt;span&gt;DEFAULT&lt;/span&gt; (getdate()),&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt;  &lt;span&gt;CONSTRAINT&lt;/span&gt; [PK_CurrencyRate_CurrencyRateID] &lt;span&gt;PRIMARY&lt;/span&gt; &lt;span&gt;KEY&lt;/span&gt; &lt;span&gt;CLUSTERED&lt;/span&gt; &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum10"&gt;  10:&lt;/span&gt; (&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum11"&gt;  11:&lt;/span&gt;     [CurrencyRateID] &lt;span&gt;ASC&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum12"&gt;  12:&lt;/span&gt; )&lt;span&gt;WITH&lt;/span&gt; (IGNORE_DUP_KEY = &lt;span&gt;OFF&lt;/span&gt;) &lt;span&gt;ON&lt;/span&gt; [&lt;span&gt;PRIMARY&lt;/span&gt;]&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum13"&gt;  13:&lt;/span&gt; ) &lt;span&gt;ON&lt;/span&gt; [&lt;span&gt;PRIMARY&lt;/span&gt;]&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If we want to have updateable partitioned view, we need to modify the constraint to include date part, which will allow the execution engine to identify partition that has to be modified during DML operation. The easiest is to add the CurrencyRateDate column to the primary key.&lt;/p&gt;

&lt;p&gt;Let’s create four tables then, one for each year of the data. I will not place here whole DDL for all tables, you can find it in the attached file. This is however the first partition table:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="border:1px solid silver;padding:4px;font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
  &lt;div id="codeSnippet" style="padding:0px;font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; &lt;span&gt;CREATE&lt;/span&gt; &lt;span&gt;TABLE&lt;/span&gt; [Sales].[CurrencyRate_2001](&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt;     [CurrencyRateID] [&lt;span&gt;int&lt;/span&gt;] &lt;span&gt;IDENTITY&lt;/span&gt;(1,1) &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt;     [CurrencyRateDate] [datetime] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt;     [FromCurrencyCode] [&lt;span&gt;nchar&lt;/span&gt;](3) &lt;span&gt;COLLATE&lt;/span&gt; Latin1_General_CI_AS &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt;     [ToCurrencyCode] [&lt;span&gt;nchar&lt;/span&gt;](3) &lt;span&gt;COLLATE&lt;/span&gt; Latin1_General_CI_AS &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt;     [AverageRate] [money] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt;     [EndOfDayRate] [money] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt;     [ModifiedDate] [datetime] &lt;span&gt;NOT&lt;/span&gt; &lt;span&gt;NULL&lt;/span&gt; &lt;span&gt;CONSTRAINT&lt;/span&gt; [DF_CurrencyRate_2001_ModifiedDate]  &lt;span&gt;DEFAULT&lt;/span&gt; (getdate()),&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span&gt;constraint&lt;/span&gt; CHK_CurrencyRateDate_2001 &lt;span&gt;CHECK&lt;/span&gt; (CurrencyRateDate&amp;gt;= &lt;span&gt;'20010101'&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; CurrencyRateDate &amp;lt; &lt;span&gt;'20020101'&lt;/span&gt;),&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum10"&gt;  10:&lt;/span&gt;  &lt;span&gt;CONSTRAINT&lt;/span&gt; [PK_CurrencyRate_2001_CurrencyRate_2001ID] &lt;span&gt;PRIMARY&lt;/span&gt; &lt;span&gt;KEY&lt;/span&gt; &lt;span&gt;CLUSTERED&lt;/span&gt; &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum11"&gt;  11:&lt;/span&gt; (&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum12"&gt;  12:&lt;/span&gt;     [CurrencyRateID] &lt;span&gt;ASC&lt;/span&gt;,&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum13"&gt;  13:&lt;/span&gt;     [CurrencyRateDate] &lt;span&gt;ASC&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum14"&gt;  14:&lt;/span&gt; )&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum15"&gt;  15:&lt;/span&gt; ) &lt;span&gt;ON&lt;/span&gt; [&lt;span&gt;PRIMARY&lt;/span&gt;]&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;As you see above, the CurrencyRateDate column has been included into the primary key of the table and I added constraint CHK_CurrencyRateDate_2001 that will take care of the range of dates that can exist in the table. You can use inequality constraint if you’d like to store rows for dates from 2001 or older. Tables for 2002, 2003 and 2004 contain constraints disallowing inserting data outside of the ranges, similar to the the constraint shown above.&lt;/p&gt;

&lt;p&gt;I removed identity column from partition tables to make the view updateable – this is one of requirements.&lt;/p&gt;

&lt;p&gt;The view is defined as follows:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="border:1px solid silver;padding:4px;font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
  &lt;div id="codeSnippet" style="padding:0px;font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; &lt;span&gt;create&lt;/span&gt; &lt;span&gt;view&lt;/span&gt; Sales.vCurrencyRate&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt; &lt;span&gt;as&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; * &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate_2001&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt; &lt;span&gt;union&lt;/span&gt; &lt;span&gt;all&lt;/span&gt; &lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; * &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate_2002&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt; &lt;span&gt;union&lt;/span&gt; &lt;span&gt;all&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; * &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate_2003&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt; &lt;span&gt;union&lt;/span&gt; &lt;span&gt;all&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; * &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate_2004&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Let’s insert some data to the view – that is, the underlying partition tables:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="border:1px solid silver;padding:4px;font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
  &lt;div id="codeSnippet" style="padding:0px;font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;
    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; insert Sales.vCurrencyRate&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt; (&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt;     [CurrencyRateID],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt;     [CurrencyRateDate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt;     [FromCurrencyCode],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt;     [ToCurrencyCode],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt;     [AverageRate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt;     [EndOfDayRate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt;     [ModifiedDate]&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum10"&gt;  10:&lt;/span&gt; )&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum11"&gt;  11:&lt;/span&gt; &lt;span&gt;select&lt;/span&gt; [CurrencyRateID],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum12"&gt;  12:&lt;/span&gt;     [CurrencyRateDate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum13"&gt;  13:&lt;/span&gt;     [FromCurrencyCode],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum14"&gt;  14:&lt;/span&gt;     [ToCurrencyCode],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum15"&gt;  15:&lt;/span&gt;     [AverageRate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;text-align:left;"&gt;&lt;span id="lnum16"&gt;  16:&lt;/span&gt;     [EndOfDayRate],&lt;/pre&gt;


    &lt;pre style="padding:0px;font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-style:none;line-height:12pt;font-family:'Courier New',courier,monospace;background-color:white;text-align:left;"&gt;&lt;span id="lnum17"&gt;  17:&lt;/span&gt;     [ModifiedDate] &lt;span&gt;from&lt;/span&gt; Sales.CurrencyRate&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt; This is the execution plan created for the insert:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/piotr_rodak/PVInsert1_031453D3.jpg"&gt;&lt;img src="http://sqlblog.com/blogs/piotr_rodak/PVInsert1_thumb_0DD43BD9.jpg" title="PVInsert1" style="border:0px none;display:inline;" alt="PVInsert1" border="0" height="381" width="826"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt; As you see, database engine split data amongst all partition tables according to the partitioning column constraints. This way, you can easily move data from one table to several smaller partitions. Of course, you wouldn’t want to run simple insert statement as above for 135 million rows, but you get the idea.&lt;/p&gt;

&lt;p&gt;Partitioned views can be very useful, but apart from the conditions that I listed earlier in this article, there are some catches that might bite you and you have to carefully ponder on your design if you want to make them updateable.&lt;/p&gt;

&lt;p&gt;These are some of these gotchas:&lt;/p&gt;

&lt;p&gt;Tables referenced in updateable partitioned views cannot have identity column. If they have, you will get following error message:&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000" face="Courier New" size="2"&gt;Msg 4433, Level 16, State 4, Line 3 
    &lt;br&gt;Cannot INSERT into partitioned view 'AdventureWorks.Sales.vCurrencyRate' because table '[AdventureWorks].[Sales].[CurrencyRate_2001]' has an IDENTITY constraint.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Tables cannot have computed columns if you want to have updateable partitioned view. If you try to insert rows into view on tables that have such columns, the error message is following:&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000" face="Courier New" size="2"&gt;Msg 4406, Level 16, State 1, Line 1 
    &lt;br&gt;Update or insert of view or function 'Sales.vSalesOrderHeader' failed because it contains a derived or constant field.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;The partitioning column has to be defined using equality or inequality operators. For example, you cannot use datepart(year, …) to defined date range for the column, you have to use either BETWEEN.. AND.. or &amp;gt;=.. &amp;lt; operator. Otherwise the error message will be as follows:&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000" face="Courier New" size="2"&gt;Msg 4436, Level 16, State 12, Line 3 
    &lt;br&gt;UNION ALL view 'AdventureWorks.Sales.vCurrencyRate' is not updatable because a partitioning column was not found.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The partitioned views do not have to be updateable. You can design tables with computed columns, IDENTITY columns and still use partitioned views to offload certain queries. One of the scenarios is for example daily upload of data. You can create a staging table which will accept the data and after ETL is finished, you alter view definition to include new table and possibly exclude one with older data.&lt;/p&gt;

&lt;p&gt;I attach the script for your convenience. You can run it on AdventureWorks database or use it as a template for your code.&lt;/p&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=28689" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/piotr_rodak/attachment/28689.ashx" length="14924" type="application/x-zip-compressed" /><category domain="http://sqlblog.com/blogs/piotr_rodak/archive/tags/partitioned+views/default.aspx">partitioned views</category><category domain="http://sqlblog.com/blogs/piotr_rodak/archive/tags/T-SQL/default.aspx">T-SQL</category><category domain="http://sqlblog.com/blogs/piotr_rodak/archive/tags/database+design/default.aspx">database design</category><category domain="http://sqlblog.com/blogs/piotr_rodak/archive/tags/performance/default.aspx">performance</category><category domain="http://sqlblog.com/blogs/piotr_rodak/archive/tags/tips+and+tricks/default.aspx">tips and tricks</category></item></channel></rss>