<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Facility9 &#187; SQL</title>
	<atom:link href="http://facility9.com/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://facility9.com</link>
	<description>Jeremiah Peschka - professional something or other</description>
	<lastBuildDate>Fri, 06 Jan 2012 15:00:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>My Code Isn&#8217;t Fat, It&#8217;s Just Robust</title>
		<link>http://facility9.com/2011/11/my-code-isnt-fat-its-just-robust/</link>
		<comments>http://facility9.com/2011/11/my-code-isnt-fat-its-just-robust/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 17:00:34 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=2341</guid>
		<description><![CDATA[I&#8217;ve been working on implementing some infrastructure code for a client. We&#8217;re building robust partition swapping to make it easy to load data without disrupting user queries. We&#8217;re doing everything eles the right way, but partition swapping makes it really easy to correct a bad load of a past data. The upside is that this&#8230;]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on implementing some infrastructure code for a client. We&#8217;re building robust partition swapping to make it easy to load data without disrupting user queries. We&#8217;re doing everything eles the right way, but partition swapping makes it really easy to correct a bad load of a past data.</p>
<p>The upside is that this code is really easy to write. There are enough examples, samples, and previous samples out there that a lot of the basics can be easily implemented. Even the complex parts of implementing the partition swapping are fairly trivial. The trick is making the code robust enough to handle almost any failure scenario.</p>
<p>Table partitioning is good to use in different ETL scenarios, but we never want it to fail. If it does fail, we want to make sure that we&#8217;re in a recoverable state. Likewise, this code needs to be automated and recover from any potential failures.</p>
<p>It turns out that the actual functionality is just a few lines of code. The robust error handling, logging, and recovery code is about 30 times longer than the functionality. It can be difficult to go through the code and update all of the error handling and logic in response to minor changes to business requirements, but the end product is a stable piece of functionality.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2011/11/my-code-isnt-fat-its-just-robust/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing for Performance</title>
		<link>http://facility9.com/2010/10/testing-for-performance/</link>
		<comments>http://facility9.com/2010/10/testing-for-performance/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 13:00:56 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1949</guid>
		<description><![CDATA[You know that you should be testing your code. You even know that you should be testing your SQL. But why? We need to make sure that changes to our code are safe, prevent regressions, and that we catch edge cases. But are you testing your code for performance? Changes to code can make your&#8230;]]></description>
			<content:encoded><![CDATA[<p>You know that you should be testing your code. You even know that you should be testing your SQL. But why? We need to make sure that changes to our code are safe, prevent regressions, and that we catch edge cases.</p>
<p>But are you testing your code for performance?</p>
<div id="attachment_1952" class="wp-caption aligncenter" style="width: 566px"><a href="http://d1kpgdt94igfig.cloudfront.net/wp-content/uploads/2010/10/troubleshootLOG.jpeg"><img src="http://d1kpgdt94igfig.cloudfront.net/wp-content/uploads/2010/10/troubleshootLOG.jpeg" alt="Are you testing for performance? You can bet these people are." title="Test your SQL" width="400" height="140" class="wp-image-1952" /></a><p class="wp-caption-text">Are you testing for performance? You can bet these people are.</p></div>
<p>Changes to code can make your code faster or slower, depending on indexing as well as user defined functions and built-in functions. Different computations can result in different in different execution plans. If changes to your code can cause drastic changes to your application performance, why aren&#8217;t you monitoring the performance of your code?</p>
<p>Test frameworks, like <a href="http://sourceforge.net/apps/trac/tsqlunit/">T-SQL Unit</a>, make it possible to wrap the execution of your stored procedures in other processes. By taking advantage of these hooks it&#8217;s possible to time the execution of each procedure and record the results in a table (possibly even correlating each run to the appropriate version from source control). You can see how query performance changes over time.</p>
<p>Testing your code is important &#8211; you can prevent changes from causing both logical <strong>and</strong> performance problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/10/testing-for-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Tutorial &#8211; Inserting Data</title>
		<link>http://facility9.com/2010/08/postgresql-tutorial-inserting-data/</link>
		<comments>http://facility9.com/2010/08/postgresql-tutorial-inserting-data/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 13:00:16 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[pg_syndication]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1699</guid>
		<description><![CDATA[In the last two articles, we talked about creating your first PostgreSQL database, the syntax of createdb and psql, and creating tables in the database. Next up, we&#8217;re going to look at filling those tables with data. createdb -U jeremiah pagila psql -U jeremiah -f pagila-schema.sql pagila psql -U jeremiah -f pagila-insert-data.sql pagila Loading Data&#8230;]]></description>
			<content:encoded><![CDATA[<p>In the last two articles, we talked about creating your first PostgreSQL database, the syntax of <strong>createdb</strong> and <strong>psql</strong>, and creating tables in the database. Next up, we&#8217;re going to look at filling those tables with data.</p>
<pre><code>createdb -U jeremiah pagila
psql -U jeremiah -f pagila-schema.sql pagila
psql -U jeremiah -f pagila-insert-data.sql pagila
</code></pre>
<h3 id="loading_data_from_a_file">Loading Data From A File</h3>
<p>We&#8217;re going to be looking at the <code>pagila-insert-data.sql</code> file. There is a separate file, <code>pagila-data.sql</code>, but we will not be using it. Both files accomplish the same purpose, but <code>pagila-insert-data.sql</code> uses standard SQL syntax whereas <code>pagila-data.sql</code> uses the <code>COPY</code> command do the bulk of the work. Since our goal is to familiarize ourselves with basic SQL, we&#8217;re going to use <code>pagila-insert-data.sql</code>.</p>
<h3 id="preparation_is_key">Preparation is Key</h3>
<p>The first thing you will notice is that there are close to 100 lines of options and comments (comments are start with <code>--</code> and end at the end of the current line) before we get to the actual meat of the file. This is because we need to set up common settings before we start working. Let&#8217;s take a look at these options line by line.</p>
<pre><code>SET client_encoding = 'UTF8';
</code></pre>
<p>Strings will be treated as Unicode strings. This makes sure that characters from non-Latin alphabets can easily be inserted into the database.</p>
<pre><code>SET standard_conforming_strings = off;
</code></pre>
<p>The <code>standard_conforming_strings</code> setting ensures some backwards compatibility with PostgreSQL behavior &#8211; we can use &#8216;&#39; as an escape character in strings. When this is set to <code>off</code>, PostgreSQL will use the &#8216;&#39; as an escape character. The goal is to, some day, default this setting to <code>on</code>.</p>
<pre><code>SET check_function_bodies = false;
</code></pre>
<p>We are, in effect, recovering from a database dump. By setting <code>check_function_bodies</code> to <code>false</code> we tell PostgreSQL that we want to put off a lot of checks until later because things might not be completely set up at the moment and we&#8217;ll accept the risks of doing this, thanks. I would never recommend using this setting in a production environment <strong>unless</strong> you&#8217;re recovering from a data dump. If that&#8217;s the case, knock yourself out.</p>
<pre><code>SET client_min_messages = warning;
</code></pre>
<p>This controls the amount of messages that we are going to receive from PostgreSQL. Leaving this alone is a good thing but it&#8217;s important to know that you can mute all messages from the server if you so desire.    </p>
<pre><code>SET escape_string_warning = off;
</code></pre>
<p>The <code>escape_string_warning</code> setting actually goes along with the <code>standard_conforming_strings</code> setting and has to do with how PostgreSQL will behave when it encounters a &#8216;&#39; character rampaging about in our code.</p>
<pre><code>SET search_path = public, pg_catalog;
</code></pre>
<p>There&#8217;s a history in the PostgreSQL world of omitting the schema qualification from table names in queries. So, what we&#8217;re doing here, is telling PostgreSQL that we would like to look for table first in the <code>public</code> database schema and then, second, in the <code>pg_catalog</code> schema. Don&#8217;t worry if you don&#8217;t know what schemas are all about, I&#8217;ll explain them later. Right now you can think of schemas as if they were folders for holding tables, functions, and the like. The <code>search_path</code> variable works just like the <code>PATH</code> variable on your operating system &#8211; it&#8217;s where PostgreSQL is going to look for functionality.</p>
<h3 id="the_anatomy_of_an_insert">The Anatomy of an Insert</h3>
<p>I wish that I could tell you that there is something complex going on with the pagila inserts. But, unfortunately, they&#8217;re about as boring as an insert could possibly be:</p>
<pre><code>INSERT INTO  -- PostgreSQL needs to listen up, we have
             -- data coming in.
actor        -- We're adding data to the actor table,
             -- specifically into the following columns
(actor_id, first_name, last_name, last_update)
VALUES       -- and here is a list of the values that
             -- we are going to insert.
(1, 'PENELOPE', 'GUINESS', '2006-02-15 09:34:33');
</code></pre>
<p>That&#8217;s all there is to a basic insert statement &#8211; we tell PostgreSQL that we want to add a new row to the database in a specific table and then supply a list of columns and values that we would like to add. Similar code happens about several hundred more times in that file. </p>
<p>This is made slightly more interesting by <code>ALTER TABLE actor DISABLE TRIGGER ALL;</code>. This code ensures that any and all triggers on the table <code>actor</code> will not fire while we&#8217;re inserting our rows. Why would we want to bypass all of the triggers? Well, we don&#8217;t want any extra validation to run, nor do we want a trigger to run that will populate the primary key column of our tables with the value from a sequence &#8211; we already have those values and our insert scripts would be much more complicated if they were filled with lookup queries too.</p>
<h3 id="adding_a_brand_new_record">Adding a Brand New Record</h3>
<p>Let&#8217;s go ahead and add a new movie. Pagila is a movie rental store and we&#8217;re not going to be able to keep up with the competition without adding a new movie. Keeping with Pagila&#8217;s standard of using nothing but gibberish movie tiles, we&#8217;re going to be adding the movie &#8220;Poseidon Sundance.&#8221;</p>
<p>Of course, creating the movie is not as easy as simply adding the title and walking away. People need to be able to make sure that the movie is acceptable for their tastes, has their favorite actor, or maybe just find out if the film is kid friendly.</p>
<pre><code>INSERT INTO film
-- Here we specify the table where we're going to add the data,
--  and then list the columns where we're going to actually
--  add the data. You don't need to list out all of the
--  columns.
-- P.S. Lines that start with two lines like this are comments.
--  The PostgreSQL command parser will ignore them.
(
  title,
  description,
  release_year,
  language_id,
  original_language_id,
  rental_duration,
  rental_rate,
  length,
  replacement_cost,
  rating
)
VALUES
(
  'POSEIDON SUNDANCE',
  'A thrilling story of a dog and a moose who have to journey across Finland to be reunited with their owners',
  '2006',
  1, -- language_id, this is English
  6, -- original_language_id, this is German
  3, -- rental_duration
  4.99, -- rental_rate
  114, -- length in minutes
  24.99,
  'G'::mpaa_rating
) ;

SELECT * FROM film WHERE title = 'POSEIDON SUNDANCE' ;

-- Ee need to put the film into categories so people can find it.
INSERT INTO film_category
(
  film_id,
  category_id
)
SELECT  film_id ,
        9 -- It's a  foreign film
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;
/* This is also a comment. It's a multi-line comment, just like in
   C++, C#, or Java.

   We're combining an INSERT with a SELECT because we need to find out
   the film_id of the movie we just added. There are occasions where
   we could take a different route, but we'll cover those later.
 */

INSERT INTO film_category
(
  film_id,
  category_id
)
SELECT  film_id ,
        8 -- films about animals are almost always family movies
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;

-- Add the main actors
INSERT INTO film_actor
(
  actor_id,
  film_id
)
SELECT  71 ,
        film_id
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;

INSERT INTO film_actor
(
  actor_id,
  film_id
)
SELECT  123 ,
        film_id
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;

INSERT INTO film_actor
(
  actor_id,
  film_id
)
SELECT  97 ,
        film_id
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;

INSERT INTO film_actor
(
  actor_id,
  film_id
)
SELECT  49 ,
        film_id
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;

INSERT INTO film_actor
(
  actor_id,
  film_id
)
SELECT  3 ,
        film_id
FROM    film
WHERE   title = 'POSEIDON SUNDANCE' ;
</code></pre>
<p>Once we&#8217;ve created our movie, let&#8217;s try to find it in the database. We can do this by writing a simple query. Don&#8217;t worry if you don&#8217;t understand everything that&#8217;s going on, everything is going to be explained in good time.</p>
<pre><code>SELECT  *
FROM    film f
        JOIN film_actor fa ON f.film_id = fa.film_id
WHERE   f.title = 'POSEIDON SUNDANCE' ;
</code></pre>
<p>If you&#8217;ve done everything right, this should return five rows &#8211; one for each actor in the movie.</p>
<pre><code>SELECT  *
FROM    film f
        JOIN film_category fc ON f.film_id = fc.film_id
WHERE   f.title = 'POSEIDON SUNDANCE' ;
</code></pre>
<p>And this should only return two rows &#8211; one for every category the movie is in.</p>
<h4 id="a_flaw_in_the_plan">A Flaw in the Plan</h4>
<p>When I was originally writing this tutorial, I didn&#8217;t pay any attention to some of the views in the database that use the film table (views are magical virtual tables that we&#8217;ll talk about later). I was getting ready to test things and I discovered a big flaw in and I thought I would highlight it here.</p>
<pre><code>SELECT  *
FROM    film_list fl
WHERE   fl.title = 'POSEIDON SUNDANCE' ;
</code></pre>
<p>This will return two rows for you. Why?</p>
<p>Well, it turns out whoever wrote the <code>film_list</code> view assumed that each movie will only belong to one category even though it can feasibly belong to as many as we want. There are a few places that we could fix this error. Before reading on see if you can think of how we could fix this.</p>
<h4 id="fixing_the_flaw">Fixing the Flaw</h4>
<p>There are multiple places we could fix this. The first place would be in the definition of the view. We could change the view to display all of the categories in a comma separated list, just like we&#8217;re doing for all of the actors in the film.</p>
<p>The next place that we can fix this is in the data itself. Apart from deleting the extra row, we can do one of two things. We can create a uniqueness requirement (called a unique constraint) on the <code>film_category</code> table so that only one film can be in the table at a time. This is a limiting feature of the application. My preference would be to create a unique constraint on both the <code>film_id</code> and <code>category_id</code> columns. That ensures that we will never have a duplicated row for a film and category combination, but we can still add multiple categories. Combining this with changes to the view fixes this flaw in our database design.</p>
<p>We&#8217;ll cover this issue later.</p>
<h3 id="summary">Summary</h3>
<p>So, there you have it &#8211; inserts are very simple statements. We can insert entirely new data that comes from somewhere outside of the database, we can insert data that&#8217;s a mash up of other information in the database, or we can do something in between. </p>
<p>What&#8217;s important to take away from this is that it&#8217;s very easy to insert information into PostgreSQL. We tell PostgreSQL that we&#8217;re going to insert data into a table, list the columns that we&#8217;re going to fill with data, and then define the data that we&#8217;re going to insert.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/08/postgresql-tutorial-inserting-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Tutorial &#8211; Referring to Other Tables</title>
		<link>http://facility9.com/2010/08/postgresql-tutorial-referring-to-other-tables/</link>
		<comments>http://facility9.com/2010/08/postgresql-tutorial-referring-to-other-tables/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 13:00:33 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[pg_syndication]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1697</guid>
		<description><![CDATA[Referring to Other Tables In the previous article you learned how to create a single table. One table does not make for a very interesting database. Since we looked at how the actor table was created, let&#8217;s take a look at the most logical follow up: the film table. The film table Without going into&#8230;]]></description>
			<content:encoded><![CDATA[<h1 id="referring_to_other_tables">Referring to Other Tables</h1>
<p>In the <a href='http://facility9.com/2010/07/28/postgresql-tutorial-creating-the-pagila-schema' target='_blank'>previous article</a> you learned how to create a single table. One table does not make for a very interesting database. Since we looked at how the <code>actor</code> table was created, let&#8217;s take a look at the most logical follow up: the <code>film</code> table.</p>
<h3 id="the_film_table">The <code>film</code> table</h3>
<p>Without going into all of the details of the <code>film</code> table, we do know that the table looks something like this:</p>
<pre><code>CREATE TABLE public.film  (
    film_id                 int4 NOT NULL DEFAULT nextval('film_film_id_seq'::regclass),
    title                   varchar(255) NOT NULL,
    description             text NULL,
    release_year            year NULL,
    language_id             int2 NOT NULL,
    original_language_id    int2 NULL,
    rental_duration         int2 NOT NULL DEFAULT 3,
    rental_rate             numeric(4,2) NOT NULL DEFAULT 4.99,
    length                  int2 NULL,
    replacement_cost        numeric(5,2) NOT NULL DEFAULT 19.99,
    rating                  mpaa_rating NULL DEFAULT 'G'::mpaa_rating,
    last_update             timestamp NOT NULL DEFAULT now(),
    special_features        text NULL,
    fulltext                tsvector NOT NULL,
    PRIMARY KEY(film_id)
)
</code></pre>
<p>There are a few features that will be covered later &#8211; like enumerations and full text searching &#8211; but this is a pretty standard table. The one thing that&#8217;s missing, though, is a way to reference the actors in each film. We could do this by adding a number of columns (<code>actor1_id</code>, <code>actor2_id</code>, etc.) but that would become cumbersome and is not an effective way to model data.</p>
<p>The alternative is to create what is commonly called a <strong>cross reference table</strong>.</p>
<h3 id="cross_reference_tables">Cross Reference Tables</h3>
<p>A cross reference table is a simple way to create a cross reference between two objects that have a many-to-many relationship. This is typically done using a two column table &#8211; one column for the primary key of each table:</p>
<pre><code>CREATE TABLE public.film_actor  (
    actor_id    int4 NOT NULL,
    film_id     int4 NOT NULL,
    last_update timestamp NOT NULL DEFAULT now(),
    PRIMARY KEY(actor_id,film_id)
)
</code></pre>
<p>Here&#8217;s the problem: as it stands, we could insert any values into this table. The whole point of the <code>film_actor</code> table is to map <em>valid</em> actors with <em>valid</em> films. Without any restrictions in place, we can&#8217;t make sure that any actor or film id in our table isn&#8217;t changed to an invalid value.</p>
<h3 id="enter_referential_integrity">Enter Referential Integrity</h3>
<p>Referential integrity is a way of saying that every value of a column in one table must exist as a value in a column in another table. In other words: every value in the referenced column or columns must exist in the referenced table. PostgreSQL makes it easy for us to enforce referential integrity through the use of foreign keys. </p>
<p>In order to make sure that we only have valid actors in the <code>film_actor</code> table, we&#8217;ll create a foreign key:</p>
<pre><code>ALTER TABLE public.film_actor
ADD CONSTRAINT film_actor_actor_id_fkey
FOREIGN KEY (actor_id)
REFERENCES actor(actor_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
</code></pre>
<p>That&#8217;s a very shorthand way of saying</p>
<pre>The table "public.film_actor"
has a foreign key constraint named "film_actor_actor_id"
on the column "actor_id"
which references the column "actor_id" in the table "actor"
  so that every value of "actor_id" in "public.film_actor"
  must also be present in the "actor_id" column
  of the table "public.actor"
if the value of "actor_id" is changed in the "public.actor" table
  we should update all values in "public.fim_actor" that are the same
and if the value of "actor_id" is deleted from the "public.actor" table
  we should prevent that delete from happening if there are rows
  in the "public.film_actor" table with the same value
</pre>
<p>We&#8217;ll create a similar foreign key to enforce referential integrity to the <code>film</code> table:</p>
<pre><code>ALTER TABLE public.film_actor
ADD CONSTRAINT film_actor_film_id_fkey
FOREIGN KEY (film_id)
REFERENCES film(film_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
</code></pre>
<p>This foreign key is almost identical to the first one. The only difference between the two are the names of the table being referenced. If you&#8217;ve taken a look at the other tables in the database, or if you&#8217;ve looked back at the previous article about creating the schema, you may have noticed something else: all of our foreign keys reference the primary key of another table.</p>
<p>Foreign keys must refer to a unique value, this prevents us from creating a foreign key that points to any column. However, since a primary key requires every value in that column be unique, it uniquely identifies the row, we can safely create a foreign key that points to the primary key column. </p>
<p>What if we want to create a foreign key that points to a different column? We can do that too. PostgreSQL has a feature called a unique constraint. This is an internal database feature that makes it possible to ensure that all values in a column, or set of columns, are unique. A unique constraint is actually implemented as a unique index in PostgreSQL, just as it is in many databases.</p>
<pre><code>CREATE UNIQUE INDEX idx_unq_manager_staff_id
ON public.store(manager_staff_id)
</code></pre>
<p>This index wouldn&#8217;t be a good candidate for a foreign key, but it does illustrate how you can create a unique index that you can reference with a foreign key.</p>
<h3 id="references">References</h3>
<p><a href="http://database-programmer.blogspot.com/2008/01/table-design-patterns-cross-reference.html">Table Design Patterns: Cross-Reference Validation</a></p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/08/postgresql-tutorial-referring-to-other-tables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Tutorial &#8211; Creating the Pagila Schema</title>
		<link>http://facility9.com/2010/07/postgresql-tutorial-creating-the-pagila-schema/</link>
		<comments>http://facility9.com/2010/07/postgresql-tutorial-creating-the-pagila-schema/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 13:00:26 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[pg_syndication]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1692</guid>
		<description><![CDATA[In the previous article, we talked about creating your first PostgreSQL database and I went over the syntax of createdb and psql in a bit of detail. Next up, we&#8217;re going to look at creating the structure of the pagila database. createdb -U jeremiah pagila psql -U jeremiah -f pagila-schema.sql pagila psql -U jeremiah -f&#8230;]]></description>
			<content:encoded><![CDATA[<p>In the <a href='http://facility9.com/2010/07/21/postgresql-tutorial-creating-your-first-database' target='_blank'>previous article</a>, we talked about creating your first PostgreSQL database and I went over the syntax of <strong>createdb</strong> and <strong>psql</strong> in a bit of detail.</p>
<p>Next up, we&#8217;re going to look at creating the structure of the pagila database.</p>
<pre><code>createdb -U jeremiah pagila
psql -U jeremiah -f pagila-schema.sql pagila
psql -U jeremiah -f pagila-insert-data.sql pagila
</code></pre>
<h3 id="working_with_sql">Working With SQL</h3>
<p>Even though SQL is the name of the language that we use to work with data, there are two subsets of SQL that you will hear people refer to: DML and DDL.</p>
<h4 id="ddl">DDL</h4>
<p>DDL is the common abbreviation for Data Definition Language. This is the name for the part of SQL that is used for creating and modifying database structures &#8211; tables, indexes, views, etc. The <code>pagila-schema.sql</code> file is chock full of DDL and is a great introduction to how to create objects in PostgreSQL.</p>
<h4 id="dml">DML</h4>
<p>DML stands for Data Manipulation Language. This is the other subset of SQL. This is how we read, update, insert, and delete data. We&#8217;ll be talking about DML in the next article.</p>
<h3 id="tables">Tables</h3>
<p>Tables are the heart and soul of a relational database &#8211; they&#8217;re where data is stored. Let&#8217;s take a look at creating the actors table:</p>
<pre><code>CREATE TABLE public.actor  (
    actor_id    int4 NOT NULL DEFAULT nextval('actor_actor_id_seq'::regclass),
    first_name  varchar(45) NOT NULL,
    last_name   varchar(45) NOT NULL,
    last_update timestamp NOT NULL DEFAULT now(),
    PRIMARY KEY(actor_id)
)
GO
CREATE INDEX idx_actor_last_name
    ON public.actor(last_name)
GO
CREATE TRIGGER last_updated
     BEFORE UPDATE ON actor FOR EACH ROW
     EXECUTE PROCEDURE last_updated()
GO

CREATE FUNCTION last_updated() RETURNS trigger
    AS $$
BEGIN
    NEW.last_update = CURRENT_TIMESTAMP;
    RETURN NEW;
END $$
    LANGUAGE plpgsql;
</code></pre>
<p>What&#8217;s going on here? Well, we&#8217;re creating a table named actor, for starters (I&#8217;ll come back to the sequence in a minute). The actor table contains four columns: <code>actor_id</code>, <code>first_name</code>, <code>last_name</code>, and <code>last_update</code>. The <code>first_name</code> and <code>last_name</code> columns are the simplest, so I&#8217;m going to start with them.</p>
<p>Both the <code>first_name</code> and <code>last_name</code> columns store character data &#8211; strings of text. These columns store variable length character data that can hold up to 45 characters. Both of these columns have been created as <code>NOT NULL</code>. This means that the columns require a value, even if that value is an empty string. Ideally you will have additional logic in place to prevent empty strings from being stored in the database as meaningful values.</p>
<p>The <code>last_update</code> column holds a date and time. The first time a row is inserted into the actor table, the <code>last_update</code> column will default to the current date and time. There is a trigger on this table, too, that will update <code>last_update</code> with the time of the update. While <code>last_update</code> does not contain any time zone specific information, it is possible for PostgreSQL to store time zone information by using the <code>timestamp with time zone</code> data type.</p>
<p>Finally we come to the <code>actor_id</code> column. This column is used as the primary key &#8211; it uniquely identifies any row in the actor table and requires the the values in the row not be null. I&#8217;ve omitted the code to create the <code>actor_actor_id_seq</code> sequence, but I&#8217;ll summarize. A sequence is similar an <code>IDENTITY</code> column in SQL Server or an <code>AUTOINCREMENT</code> column in MySQL, it just requires manual intervention. Whenever we want to increment the value of a sequence, we need to use the <code>nextval()</code> function to get the next value from the sequence. In the <code>actor</code> table, our primary key is a 4-byte number that will automatically be incremented by 1 every time a new row is added.</p>
<p>Once we have the four main columns created, we create an index <code>idx_actor_last_name</code>. Indexes make it possible for PostgreSQL to rapidly find data in a large table. It&#8217;s possible to create an index on more than one column. In this case, though, we&#8217;ll be creating our index on just the one column. This makes it easier to find actors by their last name.</p>
<p>The last thing we do is create a trigger that runs after an update. Triggers let us run pieces of code after an event (such as an insert, update, or delete) happens on a table. The <code>last_updated</code> trigger runs a function named <code>last_updated</code> before any row is updated in the database. The <code>last_updated</code> function modifies the <code>NEW</code> database row (a virtual row used in inserts and updates on row-level triggers). This new row will be inserted into the table with a new value in the <code>last_update</code> column.</p>
<p>You&#8217;re probably wondering what&#8217;s with the <code>::regclass</code> and the <code>$$</code> when we created the function. Be patient, everything will be explained in time. Right now it&#8217;s more important to focus on the higher level concepts and slowly move into the details as time goes on.</p>
<h3 id="summary">Summary</h3>
<p>Creating a basic table is a simple operation, once you know what you want to store in it. You name the table and then supply a list of columns with a data type for each one. This helps PostgreSQL figure out the optimum way to store data on disk.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/07/postgresql-tutorial-creating-the-pagila-schema/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Tutorial &#8211; Creating Your First Database</title>
		<link>http://facility9.com/2010/07/postgresql-tutorial-creating-your-first-database/</link>
		<comments>http://facility9.com/2010/07/postgresql-tutorial-creating-your-first-database/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 13:00:04 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[pg_syndication]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1686</guid>
		<description><![CDATA[Once you&#8217;ve installed PostgreSQL (OS X Instructions) (other platforms), you&#8217;ll probably want to get started with a new database. Unfortunately PostgreSQL does not include a sample database by default. You can download the pagila sample database from the pgFoundry (direct download link). Pagila is a simple movie rental database, sort of like what you would&#8230;]]></description>
			<content:encoded><![CDATA[<p>Once you&#8217;ve installed PostgreSQL (<a href="http://facility9.com/2010/02/15/installing-postgresql-on-mac-os-x">OS X Instructions</a>) (<a href="http://wiki.postgresql.org/wiki/Detailed_installation_guides">other platforms</a>), you&#8217;ll probably want to get started with a new database. Unfortunately PostgreSQL does not include a sample database by default.</p>
<p>You can download the pagila sample database from the <a href="http://pgfoundry.org/projects/dbsamples/">pgFoundry</a> (<a href="http://pgfoundry.org/frs/download.php/1719/pagila-0.10.1.zip">direct download link</a>). Pagila is a simple movie rental database, sort of like what you would get if you ran a video rental store. It is also a port of a sample MySQL database with changes made to take advantage of PostgreSQL&#8217;s features &#8211; you can read about the differences in the README file. Installing pagila is easy: </p>
<pre><code>createdb -U jeremiah pagila
psql -U jeremiah -f pagila-schema.sql pagila
# There will be a great deal of text here about creating tables and other database
#  objects. You can read through the create file if you'd like, but we're going to be
#  taking a look around so you can hold off for a minute
psql -U jeremiah -f pagila-insert-data.sql pagila
# You should see a lot of output from psql again talking about inserting rows
#  and altering seqvals. Once again, we'll be looking at this data over
</code></pre>
<p>Before you blindly copy and paste the above and run it, let&#8217;s go over everything that we&#8217;re looking at.</p>
<h3 id="createdb">createdb</h3>
<p><strong>createdb</strong> is a command line tool that is installed with your PostgreSQL installation. This is one way to create a new database using PostgreSQL. If you supply the -e command line option (<code>createdb -U jeremiah -e pagila</code>), you can see the commands that are actually being run against PostgreSQL. In this case it&#8217;s as simple as <code>CREATE DATABASE pagila;</code>. We need to tell PostgreSQL which user we&#8217;re using to connect because only certain users have the appropriate rights to create new databases. This isn&#8217;t something that just anyone can do, after all.</p>
<h3 id="psql">psql</h3>
<p><strong>psql</strong> is a command line tool that is used to connect to your PostgreSQL databases. <strong>psql</strong> has a number of options, but I&#8217;m only going to cover the options that we&#8217;re directly using to set things up for the pagila database.</p>
<h4 id="_u">-U</h4>
<p>The <code>-U</code> option is used to specify the user name to use to connect to the database instead of the default user. Unless you&#8217;ve changed something during installation, the default user is the <code>postgres</code> admin account.</p>
<h4 id="_f_filename">-f [filename]</h4>
<p><strong>psql</strong> can operate in two modes: an interactive mode and a file input mode. Passing the <code>-f</code> option to <strong>psql</strong> will use the commands in the file <em>filename</em>. You could use the input redirection operator (&lt;), but using <code>-f</code> has the advantage of processing the file as a single batch and subsequently providing helpful line numbers in the event of an error.</p>
<h4 id="the_database">The database</h4>
<p>The last parameter we&#8217;re passing is the name of the database. If you want to connect to a database on a different host, you would use the <code>-h</code> or <code>--hostname</code> command line flag to change the database host.</p>
<h3 id="related_reading">Related Reading</h3>
<p><a href="http://www.postgresql.org/docs/8.4/static/app-createdb.html">createdb syntax</a><br />
<a href="http://www.postgresql.org/docs/8.4/static/sql-createdatabase.html">CREATE DATABASE</a><br />
<a href="http://www.postgresql.org/docs/8.4/static/app-psql.html">psql</a></p>
<h3 id="some_minutiae_about_postgresql_databases">Some Minutiae About PostgreSQL Databases</h3>
<p>PostgreSQL, like many other databases, has a vast set of features. Two of these features, collations and tablespaces, aren&#8217;t immediately important for understanding what we&#8217;re doing here, but it&#8217;s a good thing to know about them for when you get into more advanced scenarios.</p>
<h4 id="collations_and_locales">Collations and Locales</h4>
<p>When you create a new database you can also specify a collation for the database. Collations are used to determine how text is stored and sorted within PostgreSQL. You can set the collation when PostgreSQL is first configured, during database creation, or when connecting to the database. There are a few gotchas that aren&#8217;t important here, but you can read about them in the PostgreSQL documentation on <a href="http://www.postgresql.org/docs/8.4/interactive/locale.html">Local Support</a>.</p>
<h4 id="tablespaces">Tablespaces</h4>
<p>You can also specify the default tablespace when you create a new database. A tablespace is the place where database objects are stored on disk. If you&#8217;re familiar with SQL Server, you will know this as a filegroup. This is a more advanced feature and can be used to achieve incredible performance benefits by spreading physical database objects across multiple physical disks. Like collation, we&#8217;re not going to worry about tablespaces for now, but it is important to know that the feature is available.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/07/postgresql-tutorial-creating-your-first-database/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Revisiting Lady MacBeth and Her Torturous Lies</title>
		<link>http://facility9.com/2010/07/revisiting-lady-macbeth-and-her-torturous-lies/</link>
		<comments>http://facility9.com/2010/07/revisiting-lady-macbeth-and-her-torturous-lies/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 15:13:30 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[sqljackass]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1701</guid>
		<description><![CDATA[A while back, I wrote up a genius piece of code that would automatically shrink my log files whenever they grew. Kendra Little (blog &#124; twitter) completely called me out for my horrible, sneaky, developer ways. Ostensibly, I had found a solution for my rampant log growth problem. Unfortunately, I had cured the symptom and&#8230;]]></description>
			<content:encoded><![CDATA[<p>A while back, I wrote up a <a href='http://facility9.com/2010/06/17/shrink-damnd-log-shrink-i-say' target='_blank'>genius piece of code</a> that would automatically shrink my log files whenever they grew.</p>
<p>Kendra Little (<a href='http://littlekendra.com/' target='_blank'>blog</a> | <a href='http://twitter.com/kendra_little' target='_blank'>twitter</a>) completely called me out for my horrible, sneaky, developer ways. Ostensibly, I had found a solution for my rampant log growth problem. Unfortunately, I had cured the symptom and not the underlying issue. After growing tired of her savage abuse and criticism via gtalk, I looked for the source of the problem. No, not me. The other source of the problem.</p>
<p>I set up monitoring on the server in question, waited for the appropriate log death window, and then read my report. Before you think I&#8217;m using fancy tools that nobody can afford, I set up profiler and perfmon and then merged the results together.</p>
<p>The reports from the single server showed me&#8230; nothing, really. There was a lot of I/O and a backup job overlapped with a re-index by about 2 minutes. The logs also didn&#8217;t fill up. To be on the safe side, I adjusted the jobs and then sat around making frowny faces for a few minutes. Then I remembered that all of the servers are connected to the same SAN, so set up monitoring on the remaining production servers. An I/O issue on one server could start causing problems on all of the other servers.</p>
<p>This time around, the logs filled up, I received a ton of emails, and I also found out something important: all of my backups and re-indexing operations were running at the same time. My SAN was saturated on I/O throughput which was causing a the backup and re-indexing jobs to run slowly. </p>
<p>To solve the problem I looked at the average job run times and arranged the jobs so that they had much more downtime between them (to account for other issues that could slow down the jobs). This took a bit more effort than I thought just because of SLAs within the company. I also re-wrote the jobs so that the backups and re-indexes could never run at the same time and would, instead, occur in series. Once I had this change in place I waited and watched.</p>
<p>Sure enough, the incredible ever growing log file problem stopped happening (unless I do something dumb like move 30,000,000 rows of data). Moral of the story: make sure that you&#8217;re addressing the cause of the problem and not the symptoms.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/07/revisiting-lady-macbeth-and-her-torturous-lies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Indexed Views to Replace Triggers</title>
		<link>http://facility9.com/2010/07/using-indexed-views-to-replace-triggers/</link>
		<comments>http://facility9.com/2010/07/using-indexed-views-to-replace-triggers/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 13:14:11 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[indexed views]]></category>
		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1642</guid>
		<description><![CDATA[Let&#8217;s get this out of the way: I think triggers are cool. I also think triggers have their place, they just need to be used with care. One reason for this is that triggers are synchronous. That is &#8211; trigger actions will block a command from returning to the client until the the trigger&#8217;s actions&#8230;]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s get this out of the way: I think triggers are cool. I also think triggers have their place, they just need to be used with care. One reason for this is that triggers are synchronous. That is &#8211; trigger actions will block a command from returning to the client until the the trigger&#8217;s actions have completed.</p>
<p>What&#8217;s the solution? Do we run summary jobs on a regular basis? Maybe.</p>
<p>Sometimes summary jobs aren&#8217;t enough. Sometimes we have to update summarized data in real time. Let&#8217;s break out <a href="http://msftdbprodsamples.codeplex.com/" target="_blank">AdventureWorks</a> and look at an example.</p>
<p>Let&#8217;s say we have a report that shows us the total line item sales per customer broken out by year and month.</p>
<p>That&#8217;s pretty simple, right?</p>
<pre>
SELECT  p.BusinessEntityID ,
        p.FirstName ,
        p.LastName ,
        DATEPART(yyyy, soh.OrderDate) AS [Year] ,
        DATEPART(mm, soh.OrderDate) AS [Month] ,
        SUM(sod.LineTotal) AS LineItemTotal
FROM    Person.Person AS p
        INNER JOIN Sales.Customer AS c ON c.PersonID = p.BusinessEntityID
        INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID
        INNER JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID
GROUP BY p.BusinessEntityID ,
        p.FirstName ,
        p.LastName ,
        DATEPART(yyyy, soh.OrderDate) ,
        DATEPART(mm, soh.OrderDate)
ORDER BY p.BusinessEntityID ,
        [Year] ,
        [Month] ;
</pre>
<p>The problem is that this query may use a lot of CPU or disk resources. How can we avoid that? Earlier I mentioned using summary jobs. The problem is that the summary jobs will only run on a schedule and require that we maintain some kind of maintenance history of each row &#8211; even if that maintenance history is just a modification timestamp. Wouldn&#8217;t it be easier if our summary report just updated itself automagically?</p>
<p>It can! Enter the indexed view.</p>
<p>An indexed view is a regular view that has a clustered index on it. By adding the clustered index the view is persisted to disk. The upside of persisting the indexed view to disk is that there&#8217;s an automatic mechanism in place that will update the indexed view. An indexed view must have a unique clustered index so that SQL Server can identify the materialized row that must be updated in response to changes in the underlying data.</p>
<pre>
CREATE VIEW dbo.my_indexed_view
WITH SCHEMABINDING
AS
  SELECT  p.BusinessEntityID,
          p.FirstName,
          p.LastName,
          DATEPART(yyyy, soh.OrderDate) AS [Year],
          DATEPART(mm, soh.OrderDate) AS [Month],
          SUM(sod.LineTotal) AS LineItemTotal,
          COUNT_BIG(*) AS NumberOfRecords
  FROM    Person.Person AS p
          INNER JOIN Sales.Customer AS c ON c.PersonID = p.BusinessEntityID
          INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID
          INNER JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID
  GROUP BY p.BusinessEntityID,
          p.FirstName,
          p.LastName,
          DATEPART(yyyy, soh.OrderDate),
          DATEPART(mm, soh.OrderDate) ;
GO

CREATE UNIQUE CLUSTERED INDEX CX_my_indexed_view ON dbo.my_indexed_view (BusinessEntityID, [Year], [Month]) ;
</pre>
<p>We <strong>could</strong> have accomplished this using a summary table and triggers. Triggers are synchronous and updating the summary table will block our data changes from completing. In addition, if we ever want to bypass the trigger from updating (say during a huge data load) we need to disable and then enable the trigger again and then remember to update the summary table. With an indexed view we can just drop the clustered index and then recreate it when we&#8217;re done with our load processes.</p>
<p><em>Note:</em> I can&#8217;t take full credit for this question and explanation. A SQL Saturday #42 attendee sent me an email with a question about using indexed views instead of triggers.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/07/using-indexed-views-to-replace-triggers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SQL Saturday 42 Musings</title>
		<link>http://facility9.com/2010/06/sql-saturday-42-musings/</link>
		<comments>http://facility9.com/2010/06/sql-saturday-42-musings/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 11:28:55 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Speaking]]></category>
		<category><![CDATA[sqlpass]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[presenting]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[sqlsaturday]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1644</guid>
		<description><![CDATA[SQL Saturday 42 has been and gone. I don&#8217;t have a ton to say, but I wanted to try to post my thoughts on the event before they were completely gone from my mind. The people who put this event on &#8211; Dave Schutz, Stuart Johnson, Marc Kuyper, Jim Stoltz, and John Jakubowski &#8211; deserve&#8230;]]></description>
			<content:encoded><![CDATA[<p>SQL Saturday 42 has been and gone. I don&#8217;t have a ton to say, but I wanted to try to post my thoughts on the event before they were completely gone from my mind.</p>
<p>The people who put this event on &#8211; Dave Schutz, Stuart Johnson, Marc Kuyper, Jim Stoltz, and John Jakubowski &#8211; deserve a big round of applause. They put together a very strong event and it seemed like they were incredibly well prepared.</p>
<p>Despite Brent Ozar suffering from incredible jet lag, and another speaker not showing up, things went off well. Allen White and I were able to cover Brent&#8217;s time slots, but not his presentations. This led to the funny moment of an attendee walking into the room and saying &#8220;You&#8217;re not Brent Ozar.&#8221; I replied, &#8220;No, I am not, but I&#8217;m talking about SQL Server Internals, it&#8217;ll be fun.&#8221; They just said, &#8220;Oh,&#8221; and walked away. So, apparently, I&#8217;m nowhere near as engaging as Brent talking about his stupid and dangerous T-SQL tricks. Clearly they don&#8217;t know that I&#8217;m just stupid and dangerous.</p>
<p>Outside of that, things went very well. My Dynamic SQL talk went over well, although I think I need to re-work it. I felt like I was flipping back and forth between demos and code a bit too much. It gave the entire experience a jerky feel. I suspect I&#8217;m overly critical of the presentation since I&#8217;ve given it a few times, but it&#8217;s always good to improve.</p>
<p>My internals presentation wasn&#8217;t well attended &#8211; this is probably due to me not being Brent Ozar. However, that didn&#8217;t stop us from having fun talking about SQL Server Internals. If anything, having a room of 6 people made the topic more fun to talk about. We were able to digress onto different topics, delve a little bit deeper than normal, and have a lot of fun watching me not trip over an extension cord.</p>
<p>Last but not least was my Indexes and Other Free Performance Boosts. I had a full room on this &#8211; I suspect it had something to do with the word &#8220;Free&#8221; in the presentation title. This is a really fun presentation because it&#8217;s a whirlwind tour of indexes, keys, statistics, and how they work together to coax SQL Server into giving us data faster. Once again, I think I need to smooth up the code samples, but on the whole things went really well. </p>
<p>I don&#8217;t have any of the evaluations, but I hope the SQL Saturday team is able to get those out to the speakers soon. From the ones I glanced at, I did a passable job. I&#8217;m looking forward to the next event in Columbus.</p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/06/sql-saturday-42-musings/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Free Training &#8211; SQL Saturday 42</title>
		<link>http://facility9.com/2010/06/free-training-sql-saturday-42/</link>
		<comments>http://facility9.com/2010/06/free-training-sql-saturday-42/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 13:01:36 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[sqlpass]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[dynamic sql]]></category>
		<category><![CDATA[presenting]]></category>
		<category><![CDATA[SQL Saturday]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1640</guid>
		<description><![CDATA[Good news! I&#8217;m speaking at SQL Saturday 42 this Saturday. Got nothing to do? Head on down to Goodwill Columbus at 1331 Edgehill Rd, Columbus, OH. Got something to do? Cancel it. I&#8217;m excited about the presentations I&#8217;m giving &#8211; I haven&#8217;t given the indexing presentation in a long time and it should be a&#8230;]]></description>
			<content:encoded><![CDATA[<p>Good news! I&#8217;m speaking at <a href='http://sqlsaturday.com/42/eventhome.aspx' target='_blank'>SQL Saturday 42</a> this Saturday. Got nothing to do? Head on down to Goodwill Columbus at 1331 Edgehill Rd, Columbus, OH. Got something to do? Cancel it.</p>
<p>I&#8217;m excited about the presentations I&#8217;m giving &#8211; I haven&#8217;t given the indexing presentation in a long time and it should be a lot of fun. And the Dynamic SQL presentation is one of the first in the day. It&#8217;s a nice easy way (I think) to get your day started. </p>
<h3>A Dynamic World Demands Dynamic SQL</h3>
<p>Dynamic SQL is a misunderstood and much maligned part of a DBA’s tool kit – it can be used to solve difficult business problems, respond to diverse data needs, and alleviate performance problems. Many DBAs reject dynamic SQL outright as a potential source of SQL injections, being poorly performing, or just for being a hacky solution in general. Not so! Jeremiah Peschka has been making extensive use of dynamic SQL throughout his career to solve a variety of problems. He’ll set about dispelling these misconceptions and demonstrate how dynamic SQL can become a part of every DBA’s tool kit.</p>
<h3>Indexes And Other Free Performance Boosts</h3>
<p>The database is often viewed as a major performance bottleneck. There are a number of quick, easy, painless techniques that can increase the performance of an application not just by a small amount, but by orders of magnitude. These techniques includes simple indexing techniques, T-SQL techniques, and general database application design patterns that give great gains in performance. In this session, you will learn how to look at a database to identify these problem areas and how to resolve common issues that you will encounter.</p>
<h3>What else?</h3>
<p>Let&#8217;s say you&#8217;re interested in something else. What should you go see? Well, Michael Swart (<a href='http://michaeljswart.com' target='_blank'>blog</a> | <a href='http://twitter.com/MJSwart' target='_blank'>twitter</a>) put together a nice little blog post about <a href='http://michaeljswart.com/?p=737' target='_blank'>How I plan to spend my weekend</a>.</p>
<p>If you like business intelligence, I suggest you hit up Dave Rodabaugh&#8217;s presentations. I cannot speak highly enough of Dave&#8217;s work. Not only is he one of the brightest BI people I know, he&#8217;s also been a teacher, friend, and mentor to me for a long time.</p>
<p>There will be some kind of dinner/drinks/whatever going on afterwards at <a href='http://www.barleysbrewing.com/' target='_blank'>Barley&#8217;s Smokehouse</a> (<a href='http://maps.google.com/maps?ie=UTF8&amp;q=barleys+near+columbus,+oh&amp;fb=1&amp;gl=us&amp;hq=barleys&amp;hnear=Columbus,+Franklin,+Ohio&amp;ei=CwUiTODhA8OclgfxyI1q&amp;ved=0CDMQtgMwBA&amp;ll=39.966596,-83.0266&amp;spn=0.055323,0.077162&amp;z=14&amp;iwloc=B' target='_blank'>map</a>). I plan on being there for a little bit. Even if you can&#8217;t make it to the event, head on over there around 6:00PM. I&#8217;ll be there. </p>
]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/06/free-training-sql-saturday-42/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: basic
Database Caching 3/39 queries in 0.049 seconds using disk: basic
Object Caching 749/838 objects using disk: basic
Content Delivery Network via Amazon Web Services: CloudFront: d1kpgdt94igfig.cloudfront.net

Served from: facility9.com @ 2012-02-11 03:08:08 -->
