<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   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/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Postgres OnLine Journal - sql server</title>
    <link>http://www.postgresonline.com/journal/</link>
    <description>an In depth look at the PostgreSQL open source database</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.4.1 - http://www.s9y.org/</generator>
    <pubDate>Mon, 16 Apr 2012 00:10:43 GMT</pubDate>

    <image>
        <url>http://www.postgresonline.com/journal/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Postgres OnLine Journal - sql server - an In depth look at the PostgreSQL open source database</title>
        <link>http://www.postgresonline.com/journal/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>ODBC Foreign Data wrapper to query SQL Server on Window - Part 2</title>
    <link>http://www.postgresonline.com/journal/archives/249-ODBC-Foreign-Data-wrapper-to-query-SQL-Server-on-Window-Part-2.html</link>
            <category>9.1</category>
            <category>contrib spotlight</category>
            <category>fdws</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/249-ODBC-Foreign-Data-wrapper-to-query-SQL-Server-on-Window-Part-2.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=249</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=249</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;As promised in &lt;a href=&quot;http://www.postgresonline.com/journal/archives/246-ODBC-Foreign-Data-wrapper---odbc_fdw-on-windows.html&quot; target=&quot;_blank&quot;&gt;our prior article: ODBC Foreign Data wrapper on windows&lt;/a&gt;, we&#039;ll demonstrate how to query SQL Server using the Foreign Data Wrapper.  This we are testing on windows.
As far as querying SQL Server / PostgreSQL goes, the Foreign Data Wrapper still lacks many features that the &lt;a href=&quot;http://www.postgresonline.com/journal/archives/103-Using-Microsoft-SQL-Server-to-Update-PostgreSQL-Data.html&quot; target=&quot;_blank&quot;&gt;SQL Server Linked Server&lt;/a&gt; approach provides.
The key ones we find currently lacking: ability to do updates and reference a table directly from server without knowing underlying structure. That said
the Foreign data Wrapper approach has possiblity to support a lot more data sources with ease.  We&#039;ll demonstrate in subsequent articles using the &lt;b&gt;www_fdw&lt;/b&gt; to query 
web services which we&#039;ve been playing a lot with and the often packaged in &lt;b&gt;file_fdw&lt;/b&gt;. Enough of that let&#039;s start with a concrete example.&lt;/p&gt;

&lt;p&gt;Warning, this is not production ready, but seems like a very promising start and with more testing can become very robust. Although we are demonstrating odbc_fdw on windows,
it is supported on Unix via the UnixODBC, but the data sources you can query will probably be different.
I&#039;m really looking forward to how the FDW technology in PostgreSQL will push the envelop.  I&#039;ve been playing around with the &lt;b&gt;www_fdw&lt;/b&gt; as well and been impressed how easily it is to 
query webservices with SQL. A very ah-hah moment.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/249-ODBC-Foreign-Data-wrapper-to-query-SQL-Server-on-Window-Part-2.html#extended&quot;&gt;Continue reading &quot;ODBC Foreign Data wrapper to query SQL Server on Window - Part 2&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 15 Apr 2012 20:09:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/249-guid.html</guid>
    <category>fdw</category>
<category>foreign data wrapper</category>
<category>postgresql 9.1</category>
<category>sql server</category>

</item>
<item>
    <title>The Relational Model is very much alive</title>
    <link>http://www.postgresonline.com/journal/archives/236-The-Relational-Model-is-very-much-alive.html</link>
            <category>db2</category>
            <category>editor note</category>
            <category>mysql</category>
            <category>oracle</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/236-The-Relational-Model-is-very-much-alive.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=236</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=236</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;In our article &lt;a href=&quot;http://www.postgresonline.com/journal/archives/234-The-Pure-Relational-Database-is-dead.html&quot; target=&quot;_blank&quot;&gt;The Pure Relational database is dead&lt;/a&gt; there
were a lot of misunderstandings as a result of our poor choice of words.  People thought we were bashing the relational model because in their mind that was what
&lt;b&gt;pure&lt;/b&gt; meant.  I got hit with a lot of poetic insults.  I still can&#039;t think of an alternative word to use for what I meant.  Simple doesn&#039;t really do it as even relational databases with just standard types
were far from simple when you consider the planner and all the other stuff going on under the hood to protect you from the underlying storage structure.  What I was trying to say is that in the beginning most relational databases
just supported a standard set of types which you could not expand on and most people when they think relational today still think just that. That type of relational database is in my book dead or almost dead.&lt;/p&gt;

&lt;p&gt;How did this all start.  Well whenever we use something like PostgreSQL to store anything complex -- take your pick: geometry data, tree like structures which we use
ltree for, full-text query constructs, and Yes XML we get bashed by some know-it-all who has a very narrow view of what a relational database should be doing and suggesting we use a NoSQL database, a graph engine or a full text engine or normalize our data more. I have also learned XML is a dirty word to many people.  I mistakenly thought XML was a complex type people could
relate to, but turns out they can relate to it so well that it brings up tragic memories I can only equate to Post Traumatic Stress Disorder suffered by war veterans or (early or wrong) technology adopters.  That was not
my intent either.  XML was just merely an example.  I will not say you should use XML in your tables, but I will also not say you should stay clear of it as many people wanted me to say.  I will say its use is rare, but it has its place.  It has its place just as any other complex type and it has its own special needs for navigation, indexing etc. which many relational databases handle fine enough.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/236-The-Relational-Model-is-very-much-alive.html#extended&quot;&gt;Continue reading &quot;The Relational Model is very much alive&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 11 Dec 2011 13:06:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/236-guid.html</guid>
    <category>relational databases</category>
<category>relational model</category>
<category>sql</category>

</item>
<item>
    <title>The Pure Relational Database is dead</title>
    <link>http://www.postgresonline.com/journal/archives/234-The-Pure-Relational-Database-is-dead.html</link>
            <category>editor note</category>
            <category>firebird</category>
            <category>mysql</category>
            <category>oracle</category>
            <category>sql server</category>
            <category>sqlite</category>
    
    <comments>http://www.postgresonline.com/journal/archives/234-The-Pure-Relational-Database-is-dead.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=234</wfw:comment>

    <slash:comments>12</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=234</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    		&lt;p&gt;A lot of redditers took offense at our article &lt;a href=&quot;http://www.postgresonline.com/journal/archives/232-XPathing-XML-data-with-PostgreSQL.html&quot; target=&quot;_blank&quot;&gt;XPathing XML data with PostgreSQL&lt;/a&gt; 
		with the general consensus,  if you are going to be stuffing XML in a relational database where will you stop? That is not what relational databases are designed for. 
		We had comitted a sacrilegious sin and worsed yet encouraging bad habits by forcing people to think more about different options they have for storing data in a &lt;em&gt;relational database&lt;/em&gt; and god forbid demonstrating querying such columns with xml specific functions.  What were we thinking? How dare we try to query XML data with SQL?  Perhaps we were thinking like &lt;a href=&#039;http://www.spatialdbadvisor.com/oracle_spatial_tips_tricks/119/loading-and-processing-gpx-11-files-using-oracle-xmldb&#039; target=&quot;_blank&quot;&gt;this guy&lt;/a&gt; or &lt;a href=&quot;http://alastaira.wordpress.com/2011/02/09/loading-open-street-map-pois-with-sql-server-bing-maps/&quot; target=&quot;_blank&quot;&gt;this guy&lt;/a&gt;,
		both equally misguided spatial relational database folk. 
		Of course we stepped one foot further by actually defining a column as xml and dare storing data in it for later consumption rather than just an intermediary step.&lt;/p&gt;
		&lt;p&gt;If I want to store documents, that are navigateable I should be using a document database like MongoDb, CouchDB etc designed for that kind of stuff. If I&#039;ve got graphs I should be using a graph database.  This got me thinking
		that the &amp;quot;Pure Relational Database&amp;quot; is dead, and I&#039;m surprised most people don&#039;t seem to realize it.  &lt;/p&gt;
		&lt;p&gt;So while &amp;quot;Relational databases&amp;quot; have changed over the last 25 years, most people&#039;s notions of them have not kept up with the pace of its change. &lt;/p&gt;
		&lt;p&gt;First let me define what I mean by Pure.  A &lt;em&gt;pure relational database&lt;/em&gt; is one with standard &lt;em&gt;meat and potato&lt;/em&gt; types like text, dates, numbers well suited for counting money and computing how close the world is to total bankruptcy which you store as fields in a row of a table and that you then define foreign keys / constraints / primary keys on to relate them to other tables.  
		You reconstitute your real world objects by stitching these tables together with joins etc and return sets using where conditions, summarize by using group bys or other mathy like constructs. Don&#039;t get me wrong;  these are very beautiful things because they allow for easy slicing of dimensions and not having to think about all the dimensions that make up an object all at once.  In fact it was so beautiful that some people thought, &amp;quot;wow that&#039;s cool, but it would be even cooler if I could
		store more complex objects in those columns with their own specific needs for querying.&amp;quot; and so was born the &lt;em&gt;object relational database&lt;/em&gt; as some people refer to them that thought relational but also understood that different types had their own unique needs for querying, storage, indexing etc.&lt;/p&gt;
		&lt;p&gt;Nowadays most, if not all, relational like databases have standardized on some variant of SQL.  
		In essence though, the pure relational database doesn&#039;t allow you to define new types or have exotic types such as arrays, xml, graphs, geometries, rasters, sparse matrices etc. 
		Much less thinking involved and less likely you will shoot yourself in the foot by dumping a bunch of xml in a field and trying to do something with it.
		When it is used to store more complex things such as spreadsheets and other user documents, these are stored as blobs and just retrieved.  Even such use is frowned upon.&lt;/p&gt;
		
		&lt;p&gt;Well most &lt;em&gt;relational databases&lt;/em&gt; I can think of nowadays have richer types: e.g. PostgreSQL, Oracle and Firebird all support arrays as a column type. Some even allow you to define custom types and functions to support your custom types e.g. PostgreSQL (I could go on forever), Oracle has rich user defined type support too, and  SQL Server 2005+ with each version getting better and better for user defined custom types and introducing more exotic types and support infrastructure. Even MySQL/Drizzle (mostly in the form of different storage engines). Even my favorite light-weight &lt;em&gt;SQLite&lt;/em&gt; under the hood has some tricks that aren&#039;t what I would call relational.  E.g. &lt;a href=&quot;http://www.gaia-gis.it/spatialite/&quot; target=&quot;_blank&quot;&gt;Spatialite/RasterLite&lt;/a&gt; has a whole geometry type library built on SQLite with functions you can call from SQL and I&#039;m sure there are lots of middleware tools you don&#039;t know about
		using the SQLite and Firebird engine for more than &lt;em&gt;relational&lt;/em&gt; tasks (e.g. HTML5 anyone/ CAD anyone).&lt;/p&gt; 
    </content:encoded>

    <pubDate>Sat, 03 Dec 2011 11:30:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/234-guid.html</guid>
    <category>object relational</category>
<category>sql</category>
<category>xml</category>

</item>
<item>
    <title>Bulk Revoke of Permissions for Specific Group/User role</title>
    <link>http://www.postgresonline.com/journal/archives/221-Bulk-Revoke-of-Permissions-for-Specific-GroupUser-role.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>intermediate</category>
            <category>mysql</category>
            <category>q&amp;a</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/221-Bulk-Revoke-of-Permissions-for-Specific-GroupUser-role.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=221</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=221</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;div style=&#039;background-color:yellow&#039;&gt;&lt;p&gt;&lt;b&gt;UPDATE&lt;/b&gt; Turns out there is a simpler way of getting rid of roles that have explicit permissions to objects as Tom Lane pointed out in the comments.
&lt;pre&gt;&lt;code&gt;DROP OWNED BY some_role;&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;Will drop the permissions to objects a user has rights to even if they don&#039;t own the objects.  Of course this needs to be applied with caution since it will drop tables
and other things you don&#039;t want necessarily dropped.  So it is best to first run a:
&lt;br /&gt;
&lt;code&gt;REASSIGN OWNED BY some_role TO new_role;&lt;/code&gt;
And then run the DROP OWNED BY.  &lt;br /&gt;
The &lt;a href=&quot;http://www.postgresql.org/docs/9.1/static/sql-reassign-owned.html&quot; target=&quot;_blank&quot;&gt;REASSIGN OWNED BY&lt;/a&gt; which is what we did originally is not sufficient since it doesn&#039;t drop the permissions or reassign
them as we assumed it would. This is noted in the docs.&lt;br /&gt;
And then you will be allowed to 
&lt;code&gt;DROP ROLE some_role&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;One of the things that is still tricky in PostgreSQL is permission management. Even though 9.0 brought us default privileges and the like, these permissions aren&#039;t
retroactive so still a pain to deal with if you already have objects defined in your database.&lt;/p&gt;

&lt;p&gt;One of the annoyances we come across with is deleting roles.  Lets say you have a role and it has explicit permissions to an object.
PostgreSQL won&#039;t allow you to delete this role if it owns objects or has explicit permissions to objects.  In order to delete it seems you have 
to go in and clear out all those permissions.  To help with that -- we wrote a quickie script that will generate a script to revoke all permissions on objects
for a specific role.  It looks like this:&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/221-Bulk-Revoke-of-Permissions-for-Specific-GroupUser-role.html#extended&quot;&gt;Continue reading &quot;Bulk Revoke of Permissions for Specific Group/User role&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 26 Sep 2011 00:11:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/221-guid.html</guid>
    <category>postgresql 8.4</category>
<category>regex</category>
<category>regular expressions</category>

</item>
<item>
    <title>SQL Server to PostgreSQL: Converting table structure</title>
    <link>http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html</link>
            <category>basics</category>
            <category>beginner</category>
            <category>oracle</category>
            <category>plpgsql</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=219</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=219</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;We&#039;ve been working on converting some of our SQL Server apps to PostgreSQL.   In this
article we&#039;ll describe some things to watch out for and provide a function we wrote to automate some of
the conversion.&lt;/p&gt;

&lt;p&gt;Although both databases are fairly ANSI-SQL compliant, there are still differences 
with their CREATE TABLE statements, data types, and how they handle other things that makes porting applications not so trivial. &lt;/p&gt;
&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html#extended&quot;&gt;Continue reading &quot;SQL Server to PostgreSQL: Converting table structure&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 04 Sep 2011 00:33:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/219-guid.html</guid>
    <category>migration</category>
<category>oracle</category>
<category>regular expressions</category>
<category>sql server</category>

</item>
<item>
    <title>Difference Between CURRENT_TIMESTAMP and clock_timestamp() and how to exploit them</title>
    <link>http://www.postgresonline.com/journal/archives/207-Difference-Between-CURRENT_TIMESTAMP-and-clock_timestamp-and-how-to-exploit-them.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>cte</category>
            <category>db2</category>
            <category>firebird</category>
            <category>intermediate</category>
            <category>mysql</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
            <category>sql server</category>
            <category>window functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/207-Difference-Between-CURRENT_TIMESTAMP-and-clock_timestamp-and-how-to-exploit-them.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=207</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=207</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;b&gt;Question:&lt;/b&gt; &lt;p&gt;What is the difference between CURRENT_TIMESTAMP and clock_timestamp()&lt;/p&gt;

&lt;b&gt;Answer:&lt;/b&gt; &lt;p&gt;CURRENT_TIMESTAMP is an ANSI-SQL Standard variable you will find in many relational databases including PostgreSQL, SQL Server, Firebird, IBM DB2 and MySQL to name a few
that records the start of the transaction.  The important thing to keep in mind about it is there is only one entry per transaction so if you have a long running transaction,
you won&#039;t be seeing it changing as you go along.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;clock_timestamp()&lt;/b&gt; is a PostgreSQL function that always returns the current clock&#039;s timestamp.  I don&#039;t think I&#039;m alone in using it for doing simple benchmarking and other things
where for example I need to record the timings of each part of a function within the function using pedestrian RAISE NOTICE debug print statements.&lt;/p&gt;

&lt;p&gt;There is another cool way I like using it, and that is for a batch of records each with an expensive function call, benchmarking how long it takes to process each record.
One of the things I&#039;m working on is improving the speed of the &lt;a href=&quot;http://www.postgis.org/documentation/manual-svn/Extras.html#Tiger_Geocoder&quot; target=&quot;_blank&quot;&gt;tiger_geocoder&lt;/a&gt; packaged in PostGIS 2.0.  The first root of attack seemed to me would be the normalize_address function
which I was noticing was taking anywhere from 10% to 50% of my time in the geocode process. That&#039;s a ton of time if you are trying to batch geocode a ton of records. The thing is 
the function is very particular to how badly formed the address is so a whole batch could be held up by one bad apple and since the batch doesn&#039;t return until all are processed, it makes
the whole thing seem to take a while.&lt;/p&gt;

&lt;p&gt;So rather than looping thru each, I thought it would be cool if I could run the batch, but for each record have it tell me how long it took to process relative to the rest so I could get
a sense of what a problem address looks like. So I wrote this query:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax0&quot;&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;WITH&lt;/span&gt; ctbenchmark
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt;
&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt;  &lt;span class=&quot;syntax-OPERATOR&quot;&gt;*&lt;/span&gt;, 
        the_time &lt;span class=&quot;syntax-OPERATOR&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;COALESCE&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-FUNCTION&quot;&gt;lag&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;the_time&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;OVER&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;BY&lt;/span&gt; the_time&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; process_time, 
            the_time &lt;span class=&quot;syntax-OPERATOR&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; diff_from_start
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; address_1, city, state, zip, 
    &lt;span class=&quot;syntax-FUNCTION&quot;&gt;pprint_addy&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-FUNCTION&quot;&gt;normalize_address&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD2&quot;&gt;coalesce&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;address_1,&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;coalesce&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;city &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;,&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; state &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;|&lt;/span&gt; zip&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; pp_addr, 
        &lt;span class=&quot;syntax-FUNCTION&quot;&gt;clock_timestamp&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; the_time
       &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; testgeocode  LIMIT &lt;span class=&quot;syntax-DIGIT&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; foo &lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; ctbenchmark
       &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;WHERE&lt;/span&gt; process_time &lt;span class=&quot;syntax-OPERATOR&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;00:00:00.016&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;::&lt;/span&gt;interval;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which returned an output something like this:

&lt;pre&gt;
        address_1 |    city    | state |  zip   |     pp_addr  |          the_time          | process_time | diff_from_start
------------------+------------+-------+------- +-------------------------------------------+--------------+------------------
 48 MAIN ST ..    | S..        | MA    | 021..  | 48 MAIN ..   | 2011-05-10 03:24:43.078-04 | 00:00:00.032 | 00:00:00.032
 15 ...           |            | MA    | 018... | 15 GREN...   | 2011-05-10 03:24:50.796-04 | 00:00:00.031 | 00:00:07.75&lt;/pre&gt;  
    </content:encoded>

    <pubDate>Tue, 10 May 2011 04:23:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/207-guid.html</guid>
    
</item>
<item>
    <title>Using Domains to Enforce Business Rules</title>
    <link>http://www.postgresonline.com/journal/archives/205-Using-Domains-to-Enforce-Business-Rules.html</link>
            <category>advanced</category>
            <category>basics</category>
            <category>db2</category>
            <category>firebird</category>
            <category>gis</category>
            <category>oracle</category>
            <category>postgis</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/205-Using-Domains-to-Enforce-Business-Rules.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=205</wfw:comment>

    <slash:comments>9</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=205</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;We like to enforce business rules at the database level wherever
we can, for the simple reason, particularly the business we are in,  most database update happens 
outside the end-user application layer.
That is not to say you shouldn&#039;t enforce at the application level too, but that the database is the last
line of defense, is usually more self-documenting than application code can be, and also protects you from your
programmers, even when that &lt;em&gt;your programmers&lt;/em&gt; is &lt;b&gt;you&lt;/b&gt;. 
&lt;a href=&quot;http://www.postgresql.org/docs/current/interactive/sql-createdomain.html&quot; target=&quot;_blank&quot;&gt;Domains&lt;/a&gt; are objects that you will find in many high-end
standards-compliant databases.  They exist in SQL Server, Oracle, IBM Db2, Firebird, and PostgreSQL to name a few. 
Domains have existed for a really long time in PostgreSQL. In &lt;a href=&quot;http://www.postgis.org/documentation/manual-svn/Topology.html&quot; target=&quot;_blank&quot;&gt;PostGIS topology&lt;/a&gt;, &lt;a href=&quot;http://www.linkedin.com/pub/sandro-santilli/b/947/488&quot; target=&quot;_blank&quot;&gt;Sandro Santilli (usually known as strk)&lt;/a&gt;, takes advantage of them for fleshing out the topology support, and I got turned on to them by him.
With that said - let&#039;s dive into domains.&lt;/p&gt;


&lt;h4&gt;What are domains?&lt;/h4&gt;
&lt;p&gt;Domains are essentially a reusable packaging of check constraints.  You use them as if they were a custom data type.  
The nice thing about them is that they are usually transparent to applications that 
don&#039;t understand them. &lt;/p&gt;

&lt;h4&gt;Example 1: Enforce pay ending/pay day happens only on certain days of the week&lt;/h4&gt;
&lt;p&gt;Here is an example -- suppose you had a payment system, and you had a rule that the pay thru end date has to
fall on a Friday.  You could create a domain such as the following:&lt;/p&gt;

&lt;pre&gt;&lt;span class=&quot;syntax0&quot;&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;payday&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;domain&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CREATE&lt;/span&gt; DOMAIN dom_payday
  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; date
   &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CONSTRAINT&lt;/span&gt; check_dow &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CHECK&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-FUNCTION&quot;&gt;trim(to_char&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;VALUE, &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;friday&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;; 
COMMENT &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; DOMAIN dom_payday &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;Company&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;payday&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;;
&lt;/span&gt;&lt;/pre&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/205-Using-Domains-to-Enforce-Business-Rules.html#extended&quot;&gt;Continue reading &quot;Using Domains to Enforce Business Rules&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sat, 30 Apr 2011 23:48:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/205-guid.html</guid>
    <category>business rules</category>
<category>constraints</category>
<category>domain</category>
<category>postgis</category>
<category>x3d</category>

</item>
<item>
    <title>Using RETURNS TABLE vs. OUT parameters</title>
    <link>http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>db2</category>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>postgresql versions</category>
            <category>sql functions</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=201</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=201</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;In a prior article &lt;a href=&quot;http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html&quot; target=&quot;_blank&quot;&gt;Use of Out and InOut Parameters&lt;/a&gt;
we demonstrated how to use OUT parameters and INOUT parameters to return a set of records from a PostgreSQL function.
There is another approach to doing this, and that is to use the ANSI Standard RETURNS TABLE construct.  
If you come from a SQL Server or IBM DB2 background, the RETURNS TABLE construct is probably most familiar, but still
how you use it and what is legal in it is a little different than it is in SQL Server or IBM DB2.  We&#039;ll save the
contrast compare as a topic for another article.  &lt;/p&gt;

&lt;p&gt;In terms of performance between using OUT vs. RETURNS TABLE, we haven&#039;t noticed much of a difference. The main thing that is 
nice about RETURNS TABLE is just that it&#039;s syntactically more pleasing in the sense that its clearer the structure of what you are returning.&lt;/p&gt;

&lt;p&gt;In these next examples, we&#039;ll demonstrate similar examples we showed in the aforementioned article except using the 
&lt;code&gt;RETURNS TABLE&lt;/code&gt;.  
Be warned that the &lt;code&gt;RETURNS TABLE&lt;/code&gt; construct is only available for PostgreSQL 8.4+, while the OUT approach
has existed since PostgreSQL 8.1. With that said, if you need your code to work on 8.3 or lower, you can&#039;t use RETURNS TABLE.
When in doubt about a feature and you are creating code that needs to support earlier versions of PostgreSQL
(as we have to in the PostGIS development group),
or you want to get stubborn users off old antiquated versions of PostgreSQL and need a bit of ammunition  
(as we have to (on PostGIS development including our own developers - and you know who you are :) ) )
check the
&lt;a href=&quot;http://www.postgresql.org/about/featurematrix&quot; target=&quot;_blank&quot;&gt;PostgreSQL feature matrix&lt;/a&gt;.  
It will save you a lot of grief.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html#extended&quot;&gt;Continue reading &quot;Using RETURNS TABLE vs. OUT parameters&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 08 Apr 2011 02:32:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/201-guid.html</guid>
    <category>ibm db2</category>
<category>postgresql 9.0</category>
<category>sql server</category>

</item>
<item>
    <title>PostGIS in Action - E-Book final version officially out</title>
    <link>http://www.postgresonline.com/journal/archives/200-PostGIS-in-Action-E-Book-final-version-officially-out.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>cte</category>
            <category>db2</category>
            <category>editor note</category>
            <category>firebird</category>
            <category>gis</category>
            <category>oracle</category>
            <category>postgis</category>
            <category>sql functions</category>
            <category>sql server</category>
            <category>window functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/200-PostGIS-in-Action-E-Book-final-version-officially-out.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=200</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=200</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;I am happy to report, that the final proof of the PostGIS in Action E-Book got released today 
and the printed version is scheduled for release Aprill 11th, 2011 and should be available on Amazon and other locations around then. The other e-Reader formats will come after that.
You can &lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1134_177&quot; target=&quot;_blank&quot;&gt;buy from here or download the two free chapters&lt;/a&gt;, if you haven&#039;t already.&lt;/p&gt;

&lt;p&gt;Each hard-copy purchase comes with a free E-Book version.  There is a coupon in the back of the book when you get it to get the E-Book versions.&lt;/p&gt;

&lt;p&gt;Yes, I know it&#039;s been a really really long time.
On the bright side, we produced twice as much content as we had set out to do and that was with keeping things as concise as we
could get away with, still managing to cover more than we set out to cover, and stripping out as many unnecessary words as we could muster. 
So 520 pages and almost 2 years later, this is where we are.  &lt;/p&gt;
&lt;p&gt;A good chunk of the additional bulk of the book was the appendices which are about 150 pages
total and focus strictly on PostgreSQL and SQL.  After many comments from early reviewers, we thought it unfair not to have a good chunk of PostgreSQL
and just general relational database content to familiarize programmers and GIS folks with the RDBMS that PostGIS lives in.  Most GIS folk unfortunately
have the hardest time with getting up to speed with SQL and just standard RDBMS management.&lt;/p&gt;

&lt;h4&gt;Two free chapters and accompanying code for all chapters&lt;/h4&gt;
&lt;p&gt;The two free chapters we selectively picked because we thought they would be most beneficial to newcomers and people new to relational databases.
So the free chapters are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1134_177&quot; target=&quot;_blank&quot;&gt;Chapter 1: What is a spatial database?&lt;/a&gt;  Which provides a fast paced history of PostGIS, PostgreSQL, Spatial Databases and moves into 
		an even faster journey into converting flat file restaurant locations to spatial point geometries, loading in an ESRI shapefile of roads.  Then shows you how to write standard
		spatial queries and render the results.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1134_177&quot; target=&quot;_blank&quot;&gt;Appendix C: SQL Primer&lt;/a&gt; -- goes through querying information_schemas, the common points of writing SELECT, INSERT, UPDATE, DELETE SQL statements and the finer points of using aggregate functions, Windowing constructs and common table expressions as well
	as a brief overview of how PostgreSQL stacks up with other relational databases (SQL Server, Oracle, IBM DB2, MySQL, Firebird) in SQL features.&lt;/li&gt;
	&lt;li&gt;All the chapter code and accompanying data.  It&#039;s a bit hefty at 57 MB.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So even if you don&#039;t buy our book, we hope you find the free chapters useful.&lt;/p&gt;
&lt;p&gt;You can get a more detailed listing of all the chapters from the &lt;a href=&quot;http://www.postgis.us&quot; target=&quot;_blank&quot;&gt;PostGIS in Action book site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We&#039;d like to thank all those who supported us through this long and unpredictable journey.  Hopefully we&#039;ll have several more, though hopefully 
a bit less nerve-racking than this first one.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Wed, 30 Mar 2011 12:28:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/200-guid.html</guid>
    
</item>
<item>
    <title>Why choose or not choose PostgreSQL?</title>
    <link>http://www.postgresonline.com/journal/archives/197-Why-choose-or-not-choose-PostgreSQL.html</link>
            <category>comparisons</category>
            <category>db2</category>
            <category>mysql</category>
            <category>oracle</category>
            <category>postgis</category>
            <category>postgresql versions</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/197-Why-choose-or-not-choose-PostgreSQL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=197</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=197</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;Many of our customers ask us this question so we thought we&#039;d lay down our thoughts.
The last couple of our articles have been how to do this and that in PostgreSQL, SQL Server, MySQL or having PostgreSQL coexist with an existing SQL Server install. 
A major reason for that is that in many of our projects we have a choice of what database to choose for a new piece of an application as long as it can play nicely with the existing infrastructure. 
Our core database competencies are still PostgreSQL, SQL Server, and MySQL with it leaning
more toward PostgreSQL each day.  We are perhaps somewhat unique in the PostgreSQL community in that Oracle never comes into our equation of decisions (though Oracle and PostgreSQL are perhaps more similar than the others).
Oracle is too expensive for most of our clientele
so it&#039;s a non-issue, and when our clients do have Oracle -- it&#039;s thrust upon them by thier ERP/CRM vendor and is essentially off limits to them. &lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/197-Why-choose-or-not-choose-PostgreSQL.html#extended&quot;&gt;Continue reading &quot;Why choose or not choose PostgreSQL?&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 25 Feb 2011 23:47:39 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/197-guid.html</guid>
    
</item>
<item>
    <title>SQL Server 64-bit Linked Server woes</title>
    <link>http://www.postgresonline.com/journal/archives/196-SQL-Server-64-bit-Linked-Server-woes.html</link>
            <category>9.0</category>
            <category>basics</category>
            <category>beginner</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/196-SQL-Server-64-bit-Linked-Server-woes.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=196</wfw:comment>

    <slash:comments>12</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=196</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;We were setting up another SQL Server 2005 64-bit where we needed a linked server connection to our PostgreSQL 9.0 server.  This is something we&#039;ve done before so not new and something we documented in  
&lt;a href=&quot;http://www.postgresonline.com/journal/archives/46-Setting-up-PostgreSQL-as-a-Linked-Server-in-Microsoft-SQL-Server-64-bit.html&quot; target=&quot;_blank&quot;&gt;Setting up PostgreSQL as a Linked Server in Microsoft SQL Server 64-bit&lt;/a&gt;.
What was different this time is that we decided to use the latest version of the new PostgreSQL 64-bit drivers now available main PostgreSQL site &lt;a href=&quot;http://www.postgresql.org/ftp/odbc/versions/msi/&quot; target=&quot;_blank&quot;&gt;http://www.postgresql.org/ftp/odbc/versions/msi/&lt;/a&gt;. 
Sadly these did not work for us.  They seemed to work fine in our MS Access 2010 64-bit install, but when used via SQL Server, SQL Server would choke with a message:&lt;/p&gt;

&lt;span style=&quot;color:red&quot;&gt;Msg 7350, Level 16, State 2, Line 1&lt;br /&gt;Cannot get the column information from OLE DB provider &quot;MSDASQL&quot;&lt;/span&gt; 
&lt;p&gt;If you tried to do a query with them.  You can however see all the tables via the linked server tab.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/196-SQL-Server-64-bit-Linked-Server-woes.html#extended&quot;&gt;Continue reading &quot;SQL Server 64-bit Linked Server woes&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 21 Feb 2011 19:10:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/196-guid.html</guid>
    <category>sql server</category>

</item>
<item>
    <title>Conditional Uniqueness with Partial Indexes</title>
    <link>http://www.postgresonline.com/journal/archives/195-Conditional-Uniqueness-with-Partial-Indexes.html</link>
            <category>8.2</category>
            <category>8.3</category>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>beginner</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/195-Conditional-Uniqueness-with-Partial-Indexes.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=195</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=195</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;b&gt;Question&lt;/b&gt;&lt;p&gt;You have a system of products and categories and you want a product to be allowed to be in multiple categories, but you want a product to only be allowed to be in one main category.
How do you enforce this rule in the database?&lt;/p&gt;

&lt;p&gt;Some people will say -- why can&#039;t you just deal with this in your application logic. Our general reason is that much of our updating doesn&#039;t happen at our application level. We like enforcing rules at the database
level because it saves us from ourselves. We are in the business of massaging data.  For this particular kind of example we wanted to make sure the database would provide us a nice safety net so that 
we wouldn&#039;t accidentally assign a product in two main categories.&lt;/p&gt;

&lt;b&gt;Answer&lt;/b&gt;
&lt;p&gt;There are two approaches we thought of.  One is the obvious have a primary category column and a bridge table that has secondary categories.  That is an ugly solution because when you do a query you have to do a union
and always treat the secondary categories as different from the main.  For most use-cases we don&#039;t usually care about distinguisihing primary from secondary category.&lt;/p&gt;

&lt;p&gt;The solution we finally settled on was to have one bridge table with a boolean field for if its the main category.  We enforce the only one main category requirement using a partial index.  Now not all databases support partial indexes
This is one major value of using PostgreSQL that you have so many more options for implementing logic.  &lt;/p&gt;

&lt;div style=&quot;background-color:yellow&quot;&gt;As some people noted in the comments and the reddit entry.  SQL Server 2008 has a similar feature called Filtered Indexes.  Though PostgreSQL has had partial indexes for as far back as I can remember.  This brings up an interesting point which I have observed -- if you were using PostgreSQL before, you would already know how to use the Filtered Indexes, Multi row inserts introduced in SQL Server 2008, and the SEQUENCES feature coming in SQL Server 2010. So we should all use PostgreSQL, because it teaches us how to use the newer versions of SQL Server before they come out. :)&lt;/div&gt;

&lt;p&gt;So how does the partial index solution look:  NOTE for simplicity, we are leaving out all the complimentary tables and the foreign key constraints that we also have in place.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax0&quot;&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;TABLE&lt;/span&gt; products_categories
&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;
  category_id &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NULL&lt;/span&gt;,
  product_id &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NULL&lt;/span&gt;,
  main boolean &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;DEFAULT&lt;/span&gt; false,
  orderby &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;syntax-DIGIT&quot;&gt;0&lt;/span&gt;,
  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CONSTRAINT&lt;/span&gt; products_categories_pkey &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;category_id, product_id&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;;

&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;UNIQUE&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;INDEX&lt;/span&gt; idx_products_categories_primary
  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; products_categories
  USING btree
  &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;product_id&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;WHERE&lt;/span&gt; main &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Testing it out.  It saves us and gives us a nice informative message to boot.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax0&quot;&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;we&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;our&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;safety&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;net&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;products_categories&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;category_id, product_id, main&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;syntax-DIGIT&quot;&gt;2&lt;/span&gt;,true&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;syntax-DIGIT&quot;&gt;2&lt;/span&gt;,false&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;syntax-DIGIT&quot;&gt;3&lt;/span&gt;,true&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;syntax-DIGIT&quot;&gt;2&lt;/span&gt;,true&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;;


&lt;span class=&quot;syntax-COMMENT1&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;which&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;gives&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;us&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;error&lt;/span&gt;
&lt;span class=&quot;syntax-LABEL&quot;&gt;ERROR&lt;/span&gt;&lt;span class=&quot;syntax-LABEL&quot;&gt;:&lt;/span&gt;  duplicate &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;key&lt;/span&gt; value violates &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;idx_products_categories_primary&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;syntax-LABEL&quot;&gt;DETAIL&lt;/span&gt;&lt;span class=&quot;syntax-LABEL&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;product_id&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; already &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;exists&lt;/span&gt;.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; 
    </content:encoded>

    <pubDate>Sat, 19 Feb 2011 23:12:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/195-guid.html</guid>
    
</item>
<item>
    <title>Reverse String Aggregation: Explode concatenated data into separate rows In PostgreSQL, SQL Server and MySQL</title>
    <link>http://www.postgresonline.com/journal/archives/193-Reverse-String-Aggregation-Explode-concatenated-data-into-separate-rows-In-PostgreSQL,-SQL-Server-and-MySQL.html</link>
            <category>beginner</category>
            <category>mysql</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/193-Reverse-String-Aggregation-Explode-concatenated-data-into-separate-rows-In-PostgreSQL,-SQL-Server-and-MySQL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=193</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=193</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;In our last article we talked about &lt;a href=&quot;http://www.postgresonline.com/journal/archives/191-stringagg.html&quot; target=&quot;_blank&quot;&gt;String Aggregation implementing in PostgreSQL, SQL Server, and MySQL&lt;/a&gt;.  This task is one that makes purist relational database programmers
a bit squeamish.  In this article we&#039;ll talk about the reverse of that, how do you deal with data that someone hands you delimeted in a single field and that you are asked to explode or re-sort based on some  lookup table.&lt;/p&gt;

&lt;p&gt;What are the benefits of having a structure such as? : &lt;pre&gt;&lt;code&gt;p_name |           activities
--------+--------------------------------
 Dopey  | Tumbling
 Humpty | Cracking;Seating;Tumbling
 Jack   | Fishing;Hiking;Skiing
 Jill   | Bear Hunting;Hiking
&lt;/code&gt;&lt;/pre&gt;Well for the casual programmer or simple text file database that knows nothing about JOINS and so forth, it makes it simple to pull a list of people who like Tumbling.
You simply do a WHERE &#039;;&#039; || activities || &#039;;&#039; LIKE &#039;%;Tumbling;%&#039;.  It&#039;s great for security too because you can determine security with a simple like check and also list all the security groups a member belongs in without doing anything.  
Quite easy for even the least data-skilled of programmers to work with because most procedural languages have a split function that can easily parse these into an array useful for stuffing into drop down lists and so forth. As a consultant of semi-techie people
I&#039;m often torn by the dilemma of &quot;What is the way I would program for myself vs. the way that provides the most autonomy to the client&quot;.  By that I mean
for example I try to avoid heavy-weight things like Wizards that add additional bloated dependencies or slow the speed down of an application. These bloated dependencies may provide ease to the client but make my debugging life harder. So I weight the options
and figure out which way works now and also provides me an easy escape route should things like speed or complexity become more of an issue.&lt;/p&gt;
&lt;p&gt;This brings us to the topic of, what is wrong with this model?  It can be slow because the LIKE condition you have can&#039;t easily take advantage of an index unless using a full text index so not ideal where this is the primary filtering factor.  It&#039;s also prone to pollution because
you can&#039;t easily validate that the values in the field are in your valid set of lookups or if your lookup changes, the text can be forced to change with a CASCADE UPDATE/DELETE RULE etc.  In cases where this is of minor consequence
which is many if referential integrity is not high on your list of requirements, this design is not bad.  It might make a purist throw up but oh well there is always dramamine to fall back on.  As long as you have done your cost benefit analysis, I don&#039;t think there should be any shame of following this
less than respected route.&lt;/p&gt;
&lt;p&gt;While you may despise this model, it has its place and it&#039;s a fact of life that one day someone will hand it to you and you may need to flip it around a bit.  We shall demonstrate how to do that in this article.&lt;/p&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/193-Reverse-String-Aggregation-Explode-concatenated-data-into-separate-rows-In-PostgreSQL,-SQL-Server-and-MySQL.html#extended&quot;&gt;Continue reading &quot;Reverse String Aggregation: Explode concatenated data into separate rows In PostgreSQL, SQL Server and MySQL&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 18 Jan 2011 18:50:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/193-guid.html</guid>
    
</item>
<item>
    <title>String Aggregation in PostgreSQL, SQL Server, and MySQL</title>
    <link>http://www.postgresonline.com/journal/archives/191-String-Aggregation-in-PostgreSQL,-SQL-Server,-and-MySQL.html</link>
            <category>8.2</category>
            <category>8.3</category>
            <category>8.4</category>
            <category>9.0</category>
            <category>cte</category>
            <category>db2</category>
            <category>intermediate</category>
            <category>mysql</category>
            <category>oracle</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
            <category>sql server</category>
            <category>window functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/191-String-Aggregation-in-PostgreSQL,-SQL-Server,-and-MySQL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=191</wfw:comment>

    <slash:comments>14</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=191</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;&lt;b&gt;Question:&lt;/b&gt; You have a table of people and a table that specifies the activities each person is involved
in.  You want to return a result that has one record per person and a column that has a listing of activities for each person
separated by semicolons and alphabetically sorted by activity. You also want the whole set alphabetically sorted by person&#039;s name. &lt;/p&gt;

&lt;p&gt;This is a question we are always asked and since we mentor on various flavors of databases, 
we need to be able to switch gears and provide an answer that works on the client&#039;s database. Most
often the additional requirement is that you can&#039;t install new functions in the database. This means that
for PostgreSQL/SQL Server that both support defining custom aggregates, that is out as an option.&lt;/p&gt;

&lt;p&gt;Normally we try to come up with an answer that works in most databases, but sadly the only solution that works in 
most is to push the problem off to the client front end and throw up your hands and proclaim -- &amp;quot;This ain&#039;t something that should be 
done in the database and is a reporting problem.&amp;quot;  That is in fact what many database purists do, and all I can say to them is wake up and smell the coffee before you are out of a job.  
We feel that data 
transformation is an important function of a database, and if your database is incapable of massaging the data into a format
your various client apps can easily digest, WELL THAT&#039;s A PROBLEM.&lt;/p&gt;

&lt;p&gt;We shall now document this answer rather than trying to answer for the nteenth time. For starter&#039;s
PostgreSQL has a lot of answers to this question, probably more so than any other, though some are easier to execute than others
and many depend on the version of PostgreSQL you are using.  SQL Server has 2 classes of answers neither of which is terribly appealing,
but we&#039;ll go over the ones that don&#039;t require you to be able to install .NET stored functions in your database since we said that is often a requirement.  
MySQL has a fairly
simple, elegant and very portable way that it has had for a really long time.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/191-String-Aggregation-in-PostgreSQL,-SQL-Server,-and-MySQL.html#extended&quot;&gt;Continue reading &quot;String Aggregation in PostgreSQL, SQL Server, and MySQL&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 24 Dec 2010 11:24:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/191-guid.html</guid>
    <category>common table expressions</category>
<category>mysql</category>
<category>oracle</category>
<category>postgresql 9.0</category>
<category>sql server</category>
<category>string concatenation</category>
<category>window functions</category>

</item>
<item>
    <title>greatest and least - oldies but goodies</title>
    <link>http://www.postgresonline.com/journal/archives/183-greatest-and-least-oldies-but-goodies.html</link>
            <category>8.2</category>
            <category>beginner</category>
            <category>mysql</category>
            <category>oracle</category>
            <category>other dbms</category>
            <category>q&amp;a</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/183-greatest-and-least-oldies-but-goodies.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=183</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=183</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;h4&gt;Problem: You have a set of numbers, or characters or whatever and you are trying to find the max or min of this set?&lt;/h4&gt;
&lt;p&gt;If the values are separate records in a table or query, the answer is well known and respected across all relational databases -- use the aggregate MAX and MIN functions.&lt;/p&gt;
&lt;p&gt;But what if you have a set of free wheeling numbers or text not in separate records, and you want the max or min of each.  Here is where the 
&lt;strong&gt;least&lt;/strong&gt; and &lt;strong&gt;greatest&lt;/strong&gt; functions come in handy.  &lt;/p&gt;
&lt;p&gt;PostgreSQL has had these functions for as far back as I can remember and  is not the only database to sport these marvelous functions.  Our beloved MySQL and Oracle database have these functions as well. Sadly our more beloved SQL Server even in the SQL Server 2008
variant - lacks these functions.&lt;/p&gt;


&lt;p&gt;Okay how to use these functions -- you use it like this: 
&lt;code&gt;
&lt;pre&gt;
   &lt;span class=&quot;syntax0&quot;&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;least&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;syntax-OPERATOR&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;syntax-DIGIT&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; num_least, &lt;span class=&quot;syntax-FUNCTION&quot;&gt;greatest&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;Bobby&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;, &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;Catty&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;, &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;Kitty&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; greatest_cat;&lt;/span&gt;
    
    Yields:
 num_least| greatest_cat
----------+----------
       -2 | Kitty
&lt;/pre&gt;
&lt;/code&gt;

&lt;p&gt;We would classify these functions along the lines of COALESCE.  They are like COALESCE because they take an arbitrary number of arguments and the datatype that is returned
is highest datatype that all arguments in the function can be autocast to.  If there is no autocast then well you get an error. To demonstrate, guess what happens when you do this:
&lt;/p&gt;

&lt;code&gt;SELECT least(-1, &#039;Kitty&#039;);&lt;/code&gt;

&lt;p&gt;Well do this in PostgreSQL at least in 8.3+, you get a nice slap if you haven&#039;t installed any deprecated autocasts: &lt;/p&gt;
&lt;span style=&quot;color:red&quot;&gt;ERROR:  invalid input syntax for integer: &quot;Kitty&quot;
LINE 1: SELECT least(&#039;Kitty&#039;, -1)&lt;/span&gt;

&lt;p&gt;Do this in MySQL - so friendly and forgiving, and great reader of minds and you get: &lt;/p&gt;
&lt;code&gt;-1&lt;/code&gt;
&lt;br /&gt;
&lt;strong&gt;OF COURSE&lt;/strong&gt;

&lt;p&gt;I apologize for the ambiguous sarcasm, its just sometimes I want my mind read and sometimes I don&#039;t and I just can&#039;t figure out whether today is one of those days or the other day.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 05 Nov 2010 01:50:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/183-guid.html</guid>
    <category>ansi sql</category>
<category>mysql</category>
<category>oracle</category>
<category>sql server</category>

</item>

</channel>
</rss>
