<?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 - q&amp;a</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>Wed, 25 Jan 2012 21:01:44 GMT</pubDate>

    <image>
        <url>http://www.postgresonline.com/journal/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Postgres OnLine Journal - q&amp;a - 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>True or False every which way</title>
    <link>http://www.postgresonline.com/journal/archives/241-True-or-False-every-which-way.html</link>
            <category>intermediate</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/241-True-or-False-every-which-way.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=241</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;PostgreSQL has aggregate functions called &lt;b&gt;bool_and&lt;/b&gt; and &lt;b&gt;bool_or&lt;/b&gt; which it&#039;s had for as far back as I can remember.
What do they do? given rows of premises (things that resolve to booleans), &lt;em&gt;bool_and&lt;/em&gt; will return true if all of the premises are true.  Similarly &lt;b&gt;bool_or&lt;/b&gt;
will return true if any of the premises in the set of rows is true.  What if however your boolean expressions are not in rows, but instead passed in
as a sequence of arbitrary statements of questionable fact.  We want a function like bool_or or bool_and that takes an arbitrary number of boolean arguments.  Are there functions
that fit the bill.  Indeed there are, but they don&#039;t scream out and say &lt;em&gt;I work with booleans&lt;/em&gt; because they fit into a class of function we
discussed in &lt;a href=&quot;http://www.postgresonline.com/journal/archives/239-The-wonders-of-Any-Element.html&quot; target=&quot;_blank&quot;&gt;The wonders of Any Element&lt;/a&gt; and that also happen to be &lt;a href=&quot;http://www.postgresonline.com/journal/archives/211-Variadic-Functions-in-PostgreSQL.html&quot; target=&quot;_blank&quot;&gt;variadic&lt;/a&gt; functions.
These are none other than
&lt;b&gt;greatest&lt;/b&gt; and &lt;b&gt;least&lt;/b&gt; and they are old timer functions that you can find in most versions of PostgreSQL.  We&#039;ll demonstrate how to use
all 4 with booleans in this article. It must be said that greatest and least are much more useful when applied to other data types like dates
and numbers, but we were amused at the parallel with booleans.&lt;/p&gt;

&lt;div style=&#039;background-color:yellow&#039;&gt;&lt;b&gt;Side note:&lt;/b&gt; we&#039;ve started to write our book on PostgreSQL that will be published by O&#039;Reilly.  We hope to finish this book within the next 5-7 months but have preliminary e-Book drafts before then for early purchasers to scan.
The focus of the book will be PostgreSQL 9.1 with some highlights the upcoming PostgreSQL 9.2.  Of course oldie but goodie topics are  in the book too. It&#039;s a thrill to be writing again.&lt;/div&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/241-True-or-False-every-which-way.html#extended&quot;&gt;Continue reading &quot;True or False every which way&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Wed, 25 Jan 2012 15:55:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/241-guid.html</guid>
    <category>aggregates</category>
<category>anyelement</category>
<category>bool_and</category>
<category>bool_or</category>
<category>greatst</category>
<category>least</category>

</item>
<item>
    <title>Table Inheritance and the tableoid</title>
    <link>http://www.postgresonline.com/journal/archives/240-Table-Inheritance-and-the-tableoid.html</link>
            <category>8.2</category>
            <category>8.3</category>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>9.2</category>
            <category>beginner</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/240-Table-Inheritance-and-the-tableoid.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=240</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;If I could name a number one feature I love most about PostgreSQL, it&#039;s the table inheritance feature which we described in &lt;a href=&quot;http://www.postgresonline.com/journal/archives/59-How-to-Inherit,-Unherit-and-Merge-Inherit.html&quot; target=&quot;_blank&quot;&gt;How to Inherit and Uninherit&lt;/a&gt;. A lot of people use it for table partitioning using &lt;a href=&quot;http://www.postgresonline.com/journal/archives/27-Reading-PgAdmin-Graphical-Explain-Plans.html&quot; target=&quot;_blank&quot;&gt;CONSTRAINT EXCLUSION&lt;/a&gt;.  Aside from that, in combination with PostgreSQL schema search_path (customizable by user and/or database) it makes for a very flexible abstraction tool.  For example, for many of our web apps that service many departments where each department/client wants to keep a high level of autonomy, we have a schema set aside for each 
that inherits from a master template schema.  Each department site uses a different set of accounts with the primary schema being that of the department/client so that they are hitting their own  tables. &lt;/p&gt;
&lt;p&gt;Inheritance allows us to keep data separate,do roll-up reports if we need to, use the same application front-end, and yet allows us the ability to add new columns in just one place (the master template schema).  It is more flexible than other approaches because for example we may have a city organization that need to share tables, like for example a system loaded list of funding source shared across the agency.  We can set aside these shared tables in a separate schema visible to all or have some have their own copy they can change if they don&#039;t want to use the shared one.&lt;/p&gt;

&lt;p&gt;Every once in a while, we find ourselves needing to query the whole hierarchy and needing to know which table the results of the query are coming from. To help
solve that issue, we employ the use of the system column &lt;b&gt;tableoid&lt;/b&gt; which all user tables have. The tableoid is the the object id of a table.  PostgreSQL has many system columns that you have to explicitly select
and can&#039;t be accessed with a SELECT * with the tableoid being one of them.  These are: tableoid, cmax,cmin, xmin,xmax,ctid which are all described in &lt;a href=&quot;http://www.postgresql.org/docs/9.1/static/ddl-system-columns.html&quot; target=&quot;_blank&quot;&gt;System Columns&lt;/a&gt;.  The &lt;a href=&quot;http://www.postgresql.org/docs/9.1/static/ddl-inherit.html&quot; target=&quot;_blank&quot;&gt;PostgreSQL docs on inheritance&lt;/a&gt; have examples of using it, but we thought it worthwile to repeat the exercise since it&#039;s not that common knowledge and is unique enough feature of PostgreSQL that others coming from other relational databases, may miss the treat.  I&#039;ve often demonstrated
it to non-PostgreSQL users who use for example SQL Server or MySQL, and they literally fall out of their chair when I show the feature to them and its endless possibilities.&lt;/p&gt;   &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/240-Table-Inheritance-and-the-tableoid.html#extended&quot;&gt;Continue reading &quot;Table Inheritance and the tableoid&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 16 Jan 2012 05:52:54 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/240-guid.html</guid>
    
</item>
<item>
    <title>How big is my database and my other stuff</title>
    <link>http://www.postgresonline.com/journal/archives/233-How-big-is-my-database-and-my-other-stuff.html</link>
            <category>beginner</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/233-How-big-is-my-database-and-my-other-stuff.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=233</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;In this day and age of clouds and what not, it is still important to keep tabs on your database growth to ensure it doesn&#039;t
outgrow your disks or so that you can be prepared when it does.  A common question that is asked is how big your database is or all your databases combined.
Luckily PostgreSQL has had for a long time functions to help you answer this easily.  In this little article,
I&#039;ll demonstrate how to answer these questions and more with some PostgreSQL built-in functions&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/233-How-big-is-my-database-and-my-other-stuff.html#extended&quot;&gt;Continue reading &quot;How big is my database and my other stuff&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 21 Nov 2011 01:59:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/233-guid.html</guid>
    <category>postgresql</category>

</item>
<item>
    <title>What objects are in a PostgreSQL installed extension</title>
    <link>http://www.postgresonline.com/journal/archives/231-What-objects-are-in-a-PostgreSQL-installed-extension.html</link>
            <category>9.1</category>
            <category>intermediate</category>
            <category>postgis</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/231-What-objects-are-in-a-PostgreSQL-installed-extension.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=231</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;As mentioned in &lt;a href=&quot;http://www.postgresonline.com/journal/archives/227-Lessons-learned-Packaging-PostGIS-Extensions-Part-2.html&quot;&gt;Lessons Learned Packaging PostGIS extensions&lt;/a&gt;, I am working on PostGIS 2.0.0 extension packaging.  One of the things I wanted to know was what objects, types, functions etc were installed by my extension.  The new packaging system allows for cataloging this relatively easily, but I couldn&#039;t find a function or view for this  and didn&#039;t see one mentioned in the manual, so I created this query which seems to work pretty well as far as I can tell.  The basic idea being that any object that an extension depends on 
that is not an extension is part of the extension package.&lt;/p&gt;

&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; c.relname &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; item_type, 
    &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-KEYWORD1&quot;&gt;proc&lt;/span&gt;.proname,typ.typname, cd.relname, op.oprname, 
        &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;CAST(&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; cs.typname &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;AS&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; ct.typname &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;, opcname, opfname&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; item_name,
    &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-KEYWORD1&quot;&gt;proc&lt;/span&gt;.proisagg,false&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; is_agg, &lt;span class=&quot;syntax-FUNCTION&quot;&gt;oidvectortypes&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;proc&lt;/span&gt;.proargtypes&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; arg_types
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; pg_depend &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; d &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_extension &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; e
    &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; d.refobjid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; e.oid &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_class &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; c &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt;
        c.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.classid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_proc &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;proc&lt;/span&gt;.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_type &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; typ &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; typ.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_class &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; cd &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; cd.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_operator &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; op &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; op.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_cast &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; ca &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; ca.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_type &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; cs &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; ca.castsource &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; cs.oid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_type &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;AS&lt;/span&gt; ct &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; ca.casttarget &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; ct.oid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_opclass &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; oc &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; oc.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
        &lt;span class=&quot;syntax-KEYWORD2&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;JOIN&lt;/span&gt; pg_opfamily &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; ofa &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ON&lt;/span&gt; ofa.oid &lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt; d.objid
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;WHERE&lt;/span&gt; d.deptype &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;e&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;and&lt;/span&gt; e.extname &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;postgis&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&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; item_type, item_name;
&lt;/span&gt;&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;The output looks like: &lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/231-What-objects-are-in-a-PostgreSQL-installed-extension.html#extended&quot;&gt;Continue reading &quot;What objects are in a PostgreSQL installed extension&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 03 Nov 2011 16:55:13 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/231-guid.html</guid>
    <category>extensions</category>
<category>postgis</category>

</item>
<item>
    <title>How to create an n-column table really fast</title>
    <link>http://www.postgresonline.com/journal/archives/230-How-to-create-an-n-column-table-really-fast.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>9.2</category>
            <category>beginner</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/230-How-to-create-an-n-column-table-really-fast.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=230</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;Ever have the need to create a holding table say spreadsheet data with say 100 columns. You need to create a table to hold this stuff.   Or perhaps you were feeling in a sadist mood and wanted to abuse your PostgreSQL database to see how many columns you can create in a table of a specific data type. 
Here is a quick script to do it:&lt;/p&gt;

&lt;code&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;8.4+&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;syntax&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;CREATE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;data_import(&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-FUNCTION&quot;&gt;array_to_string&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-FUNCTION&quot;&gt;array_agg&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;field&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; i&lt;span class=&quot;syntax-OPERATOR&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;text&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;varchar(255)&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-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;&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-KEYWORD1&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;generate_series&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;10&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; i;

&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;9.0+&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;syntax&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;(string_agg&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;was&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;introduced&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;9.0)&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;CREATE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;data_import(&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-FUNCTION&quot;&gt;string_agg&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;field&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; i&lt;span class=&quot;syntax-OPERATOR&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;text&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;varchar(255)&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;,&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;&#039;&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;generate_series&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;10&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; i;
&lt;/span&gt;&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;Both variants will return output that looks like this: &lt;/p&gt;
&lt;pre&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; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;data_import&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;field1 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field2 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field3 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field4 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
    ,field5 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field6 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field7 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;
    ,field8 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field9 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;,field10 &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;255&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&gt;&lt;/pre&gt;

&lt;p&gt;Now if you want it to also execute because you are running it as part of an sql script, you could wrap it in an anonymous function.&lt;/p&gt;
&lt;code&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;-wrap&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;anonymous&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;run&lt;/span&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;requires&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;PostgreSQL&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;9.0+&lt;/span&gt;
DO language &lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;plpgsql&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;
$$
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;DECLARE&lt;/span&gt; var_sql &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;text&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;CREATE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;data_import(&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-FUNCTION&quot;&gt;string_agg&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;field&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; i&lt;span class=&quot;syntax-OPERATOR&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;text&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;varchar(255)&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;,&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;&#039;&lt;/span&gt;
    &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;syntax-FUNCTION&quot;&gt;generate_series&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;10&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; i;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;BEGIN&lt;/span&gt;
    &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;EXECUTE&lt;/span&gt; var_sql;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;END&lt;/span&gt;;
$$ ;
&lt;/span&gt;&lt;/pre&gt;&lt;/code&gt;
 
    </content:encoded>

    <pubDate>Tue, 01 Nov 2011 22:31:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/230-guid.html</guid>
    <category>aggregates</category>
<category>array</category>
<category>array_agg</category>
<category>string_agg</category>

</item>
<item>
    <title>PostgreSQL Array: The ANY and Contains trick</title>
    <link>http://www.postgresonline.com/journal/archives/228-PostgreSQL-Array-The-ANY-and-Contains-trick.html</link>
            <category>intermediate</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/228-PostgreSQL-Array-The-ANY-and-Contains-trick.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=228</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;One of the main features I love about PostgreSQL is its array support.  This is a 
feature you won&#039;t find in most relational databases, and even databases that support some variant
of it, don&#039;t allow you to use it as easily.  It is one of the features that makes building
aggregate functions wicked easy in PostgreSQL with no messy compiling required.  
Aside from building aggregate functions, it has some other common day uses.  
In this article, I&#039;ll cover two common ways we use them which I will refer to as the &lt;b&gt;ANY&lt;/b&gt;
and &lt;b&gt;Contains&lt;/b&gt; tricks.&lt;/p&gt;

&lt;p&gt;I like to think of this approach as &lt;a href=&quot;http://blog.gigaspaces.com/2010/07/15/yesql-an-overview-of-the-various-query-semantics-in-the-post-only-sql-world/&quot; target=&quot;_blank&quot;&gt;YeSQL programming style&lt;/a&gt;: how SQL can be augmented by more complex data types and index retrieval mechanisms.
 Arrays and many other data types (spatial types, keyvalue (hstore), ltree etc) are far from relational structures, yet we can query them easily with SQL and can even relate them.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/228-PostgreSQL-Array-The-ANY-and-Contains-trick.html#extended&quot;&gt;Continue reading &quot;PostgreSQL Array: The ANY and Contains trick&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 27 Oct 2011 01:09:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/228-guid.html</guid>
    <category>aggregates</category>
<category>all</category>
<category>array</category>
<category>string_agg</category>
<category>yesql</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>Querying table, view, column and function descriptions</title>
    <link>http://www.postgresonline.com/journal/archives/215-Querying-table,-view,-column-and-function-descriptions.html</link>
            <category>beginner</category>
            <category>postgis</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/215-Querying-table,-view,-column-and-function-descriptions.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=215</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;One of the biggest complaints about software and perhaps even more specifically FLOSS software is the lack of documentation. I&#039;m not talking about those 
small little dialogs we throw in our code that rarely see the light of day.  I&#039;m talking about stuff you throw in user docs or specifications and so forth
that an analyst or end-user reads.&lt;/p&gt;
&lt;p&gt;The main reasons for this lack of documentation is that while everyone seems to want documentation, few really want to pay for it, and it&#039;s time consuming to keep 
documentation in synch with what the software actually does.  Having documentation that is very inconsistent with the software is worse than not having any documentation at all. 
A good way to keep documentation up to date is to fold it into the process of developing and testing the software such that changes in software expose errors in the documentation and vice-versa
or that the act of changing the software corrects the documentation.&lt;/p&gt;
&lt;p&gt;Part of the way we try to do that on the PostGIS project is to require each function patch to include documentation.  We also try to make our documentation executable 
by auto-generating PostgreSQL help and 
some test suites  from the documentation.  For example the process of installing documentation-generated function and type descriptions 
in PostgreSQL catches inconsistencies between
the implementation and what we actually publish about how the functions work.  Even the image generator that builds most of the images in the manual is built with PostGIS as a core of it
so that when our build-bot is rebuilding the documentation it is exercising some PostGIS output functions.&lt;/p&gt;

&lt;p&gt;I can&#039;t tell you how many times I&#039;ve flagged changes in the current PostGIS 2.0 release
simply by trying to install the docbook generated PostgreSQL comment descriptions and PostgreSQL complains that the function signature no longer exists that the documentations says should be there. 
So then I go back and correct
the documentation or yell at the programmer if the documentation makes more sense than what they coded. On the other side,
its easy to catch what we neglected to document simply by scanning the functions in PostgreSQL and seeing which ones don&#039;t have descriptions.  &lt;/p&gt;

&lt;p&gt;Okay as far as databases goes, many a DB Programmer/Analyst has waltzed into a project only to be befuddled about the meanings of all these tables used by the application.
If you are like us, you don&#039;t even want to look at any database documentation that is not part of the definition of the database because you know 99% of the time it&#039;s so obsolete 
or was just a pipe dream of someone working in a vacuum
that its more useless than not having any 
documentation at all. It is nice to have nicely formatted documentation you can read separate from the code, 
but even sweeter if you can query the documentation just as easily as you can query the data. &lt;/p&gt; 
&lt;p&gt;A good way of having up to date documentation is to weave it in as part of the process of defining the structure.  For databases
this means using foreign keys, primary keys, and using the commenting features that most relational databases offer these days.  For example the databases we commonly work with,
PostgreSQL, SQL Server, MS Access, and even MySQL all allow you to provide descriptions for tables, table columns, and sometimes other objects such as functions and stored procs right in the database.  PostgreSQL even allows you to provide descriptions of columns in
views though that&#039;s a bit messier to do.  Sadly there isn&#039;t a consistent way of pulling these descriptions out of the database that will work for all of these.  Each has differently defined meta tables it stores these descriptions in.
For thise article, we&#039;ll demonstrate how to pull this information from PostgreSQL.&lt;/p&gt;

&lt;p&gt;PostgreSQL does offer many useful switches in psql for querying this data, but we&#039;ll focus our attention on pulling this data via SQL. It&#039;s much easier to incorporate this information
in auto-generated documentation with SQL  because you can have more control what you include and how to format it.&lt;/p&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/215-Querying-table,-view,-column-and-function-descriptions.html#extended&quot;&gt;Continue reading &quot;Querying table, view, column and function descriptions&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 31 Jul 2011 05:07:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/215-guid.html</guid>
    <category>postgis documentation</category>

</item>
<item>
    <title>Manually setting table column statistics</title>
    <link>http://www.postgresonline.com/journal/archives/209-Manually-setting-table-column-statistics.html</link>
            <category>9.0</category>
            <category>9.1</category>
            <category>intermediate</category>
            <category>postgresql versions</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/209-Manually-setting-table-column-statistics.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=209</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;h5&gt;Question: How do you deal with bad stat counts?&lt;/h5&gt; 
&lt;p&gt;You have a large table and the default planner stats collector underestimates distinct counts of a critical query column thus resulting in much less than optimal query plans. 
How can you manually set this?&lt;/p&gt;
&lt;p&gt;PostgreSQL 9.0 introduced ability to set two settings on table columns: &lt;em&gt;n_distinct&lt;/em&gt; and &lt;em&gt;n_distinct_inherited&lt;/em&gt; which are described a bit in &lt;a href=&quot;http://www.postgresql.org/docs/current/static/sql-altertable.html&quot; target=&quot;_blank&quot;&gt;ALTER TABLE help&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;n_distinct&lt;/b&gt; is the estimated number of distinct values for that column
with -1 or any negative number representing a percentage of estimated table count instead of a true count. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;n_distinct_inherited&lt;/b&gt; is a setting useful for parent tables that denotes the estimated distinct count sum of all a parent&#039;s child tables.&lt;/p&gt;
&lt;p&gt;By tweaking these settings when they are less than optimal, you can influence the query planner to produce better plans. Why this is necessary is mostly for large
tables where the stat collector will not query the whole table to determine stats.  The stats collector generally queries at most 10-30% of a table.&lt;/p&gt;


&lt;h5&gt;Determine If you need to set counts&lt;/h5&gt;
&lt;p&gt;It&#039;s always nice to have the stat collector do all these things for you especially if you have a table that is constantly updated and distinct counts can fluctuate a lot. 
For static tables you may just want to set them manually.
So how do you know whether you should bother or not.  Well you can check the current values
the stats collector has with this query:&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;determine&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;your&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;are&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;fine&lt;/span&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; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;estimates&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;what&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;you&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;know&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;they&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;are&lt;/span&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-KEYWORD1&quot;&gt;SELECT&lt;/span&gt; tablename, schemaname, attname &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;As&lt;/span&gt; colname, n_distinct,
&lt;span class=&quot;syntax-FUNCTION&quot;&gt;array_to_string&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;most_common_vals, E&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;\n&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; common_vals,
&lt;span class=&quot;syntax-FUNCTION&quot;&gt;array_to_string&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;most_common_freqs, E&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;\n&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; dist_freq
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; pg_stats
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;WHERE&lt;/span&gt; tablename &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;table_of_interest&lt;/span&gt;&lt;span class=&quot;syntax-LITERAL1&quot;&gt;&#039;&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; schemaname, tablename, attname;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You would then compare with your actuals &lt;/p&gt;
&lt;pre&gt;&lt;code&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-KEYWORD2&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;DISTINCT&lt;/span&gt; column_of_interest&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;FROM&lt;/span&gt; table_of_interest;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will give you the current count.&lt;/p&gt;

&lt;h5&gt;Setting n_distinct and n_distinct_inherited&lt;/h5&gt;
You may want to bump this up or down when you set the value.  Next to set the column distinct count stats you would do something like below
replacing 50 with the count you computed:&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;set&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;(non&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;tables&lt;/span&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; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;TABLE&lt;/span&gt; table_of_interest
   &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;COLUMN&lt;/span&gt; column_of_interest
   &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;n_distinct&lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;50&lt;/span&gt;&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; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;(parent&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;tables&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;inheritance&lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;hierarchy&lt;/span&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; &lt;/span&gt;&lt;span class=&quot;syntax-COMMENT1&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;TABLE&lt;/span&gt; table_of_interest
   &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;COLUMN&lt;/span&gt; column_of_interest
   &lt;span class=&quot;syntax-KEYWORD1&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;syntax-OPERATOR&quot;&gt;(&lt;/span&gt;n_distinct_inherited&lt;span class=&quot;syntax-OPERATOR&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;syntax-DIGIT&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;syntax-OPERATOR&quot;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; 
    </content:encoded>

    <pubDate>Sun, 22 May 2011 10:06:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/209-guid.html</guid>
    
</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>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>
<item>
    <title>Starting PostgreSQL in windows without install</title>
    <link>http://www.postgresonline.com/journal/archives/172-Starting-PostgreSQL-in-windows-without-install.html</link>
            <category>8.2</category>
            <category>8.3</category>
            <category>8.4</category>
            <category>9.0</category>
            <category>beginner</category>
            <category>q&amp;a</category>
    
    <comments>http://www.postgresonline.com/journal/archives/172-Starting-PostgreSQL-in-windows-without-install.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=172</wfw:comment>

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

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;This is a question that comes up quite often by windows users, so thought we would share how we normally do it.  The question is can you run a PostgreSQL server on your windows desktop/server box without having to install anything?
The answer is yes and quite easily.  Why would you need to do this.  There are a couple of cases -- one you are developing a single user app that you want users to be able to run from anywhere without having to install it first.
The other common reason is, you aren&#039;t allowed to install anything on a user&#039;s pc and you also want to package along a database you already have created.&lt;/p&gt;
&lt;p&gt;For our purposes, many of our developers develop on portable WAMP like things, and for some of our applications, they need to work in both MySQL and PostgreSQL, so we need an easy way during development to swap one out for the other.&lt;/p&gt;

 &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/172-Starting-PostgreSQL-in-windows-without-install.html#extended&quot;&gt;Continue reading &quot;Starting PostgreSQL in windows without install&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 12 Aug 2010 19:25:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/172-guid.html</guid>
    
</item>

</channel>
</rss>
