<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://www.skepticats.com/LnBlog/themes/default/styles/rss.css" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<link>http://linlog.skepticats.com/feeds/ComputerScience_news.xml</link>
<title>LinLog</title>
<description>Linux, Programming, and Computing in General</description>
<generator>LnBlog 1.0.0</generator>
<item>
<title>Keys and NULLs  </title>
<link>http://linlog.skepticats.com/entries/2008/10/Keys_and_NULLs.php</link>
<description>
&lt;p&gt;Well, the cat is currently laying on the book I was trying to read, so I guess I might as well blog.&lt;/p&gt;&lt;p&gt;Note to self: the rule in SQL is that you can have NULLs in &lt;em&gt;foreign&lt;/em&gt; keys, but not in &lt;em&gt;primary&lt;/em&gt; keys.  Edwin asked me a question related to this the other day and I had to stop and think about it for a couple of minutes, so I figured I'd write it out to reinforce the concept in my own mind.&lt;/p&gt;&lt;p&gt;When you think about it, these rules make perfect sense.  Since NULLs in SQL denote an unknown or inapplicable value, having one in a primary key would be nonsense, because a primary key must uniquely identify a row.  Having a NULL in the key would mean part of the unique value was unknown.  (Note that you can't say that a tuple with a NULL in it is unique because one NULL is not equal to another due to the 3-valued logic used by SQL.)&lt;/p&gt;&lt;p&gt;As for foreign keys, SQL  gives the &amp;quot;benefit of the doubt.&amp;quot;  If you think of a NULL as an unknown value which &lt;em&gt;may&lt;/em&gt; later become known, this makes sense.  Sometimes you might have to add the values of foriegn keys in multiple operations, which would not be allowed if NULLs were blocked by the constraint.&lt;/p&gt;&lt;p&gt;From a logical point of view, this is kind of an interesting case as well.  You can view a foreign key constraint check as a conjunction of equivalence checks.  For example if T1(c1, c2) is foreign keyed to T2(c1, c2), then the constraint check can be viewed as the expression &lt;code&gt;T1.c1 = T2.c1 AND T1.c2 = T2.c2&lt;/code&gt;.  In other words, if all the key fields match on both records, the constraint is satisfied.  If not, it fails.  However, with NULLs, the value of one of the conjuncts would be NULL, which would render the entire expression NULL.  &lt;/p&gt;&lt;p&gt;But what would that mean?  &lt;/p&gt;&lt;p&gt;The &lt;abbr title=&quot;DataBase Management System&quot;&gt;DMBS&lt;/abbr&gt; can't say that it &lt;em&gt;doesn't know&lt;/em&gt; if a relational constraint holds or not.  So, given the interpretation of NULL, it makes sense to use the &amp;quot;benefit of the doubt&amp;quot; principle and defer final judgement on the constraint until all the NULLs are filled in.&lt;/p&gt;
</description>
<author>pageer@skepticats.com (Peter Geer)</author>
<comments>http://linlog.skepticats.com/entries/2008/10/11_2339/comments/</comments>
<guid>http://linlog.skepticats.com/entries/2008/10/11_2339/</guid>
</item>
<item>
<title>Updating from the same table     </title>
<link>http://linlog.skepticats.com/entries/2008/06/Updating_from_the_same_table.php</link>
<description>
&lt;p&gt;Last time, I was bitching about &lt;a href=&quot;http://linlog.skepticats.com/entries/2008/06/Another_reason_to_hate_MySQL.php&quot;&gt;doing an update based on a select from the same table in MySQL&lt;/a&gt;.  Well, after reading the chapter on &amp;quot;Views, Derived Tables, Materialized Tables, and Temporary Tables&amp;quot; in &lt;em&gt;SQL for Smarties&lt;/em&gt;, followed by a search of the MySQL documentation, I figured out a way around that annoying limitation.&lt;/p&gt;&lt;p&gt;If you recall from last time, the query that wasn't working looked something like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;mysql&amp;gt; UPDATE test_tbl SET val2 = (SELECT val2 FROM test_tbl WHERE val1 = 1) WHERE val1 = 3;&lt;br /&gt;ERROR 1093 (HY000): You can't specify target table 'test_tbl' for update in FROM clause&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Basically, this is doing an update and setting a column to the value of a scalar subquery.  The catch is that, in MySQL, this doesn't work when the select and update are on the same table.&lt;/p&gt;&lt;p&gt;Well, the trick is that you have to make make MySQL materialize the subquery.  I actually decided to try that after reading Joe Celko's story about views in the early days of DB2.  At the time, it was using inline-expansion for views, which would sometimes generate invalid SQL.  Thus it was sometimes necessary to make the database materialize the view.  &lt;/p&gt;&lt;p&gt;Well, I figured the same thing might apply here.  And so, after a little inspiration from the MySQL manual, here's a working version of the same query:&lt;/p&gt;&lt;p&gt;&lt;code&gt;UPDATE test_tbl SET val2 = (SELECT val2 FROM (SELECT val2 FROM test_tbl AS tmp1 WHERE val1=1) AS tmp2) WHERE val1 = 3;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;I stole &lt;a href=&quot;http://dev.mysql.com/doc/refman/4.1/en/subquery-restrictions.html&quot;&gt;the sub-subquery idea&lt;/a&gt; from the MySQL manual.  It is, of course, completely gratuitous from a logical standpoint, but it forces MySQL to materialize the subquery.  That, in turn, allows us to bypass the &amp;quot;no updating the same table&amp;quot; restriction, since we're technically selecting from a temporary table.&lt;/p&gt;&lt;p&gt;So there you have it!  I was wrong about not being able to do that.  It just takes a little finagling.  Of course, I still think MySQL should be smart enough to make a temporary table on its own, but at least the end result is still possible.&lt;/p&gt;
</description>
<author>pageer@skepticats.com (Peter Geer)</author>
<comments>http://linlog.skepticats.com/entries/2008/06/16_1401/comments/</comments>
<guid>http://linlog.skepticats.com/entries/2008/06/16_1401/</guid>
</item>
<item>
<title>Another reason to hate MySQL      </title>
<link>http://linlog.skepticats.com/entries/2008/06/Another_reason_to_hate_MySQL.php</link>
<description>
&lt;p&gt;I'm currently about half way through &lt;a href=&quot;http://www.amazon.com/Joe-Celkos-SQL-Smarties-Programming/dp/0123693799/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1212702882&amp;amp;sr=8-1&quot;&gt;Joe Celko's &lt;em&gt;SQL for Smarties&lt;/em&gt;&lt;/a&gt; and I've got to tell you - it's spoiling me as a &lt;acronym title=&quot;Linux, Apache, MySQL, and PHP&quot;&gt;LAMP&lt;/acronym&gt; developer.  &lt;/p&gt;&lt;p&gt;Let me start out by saying that this book is a must-read for any developer who works with databases.  Even if you've been writing SQL for years, you need to read this book.  In fact, unless you sat on the ANSI SQL-92 committee &lt;em&gt;with Joe Celko&lt;/em&gt;, you can benefit from reading this book.  I've been &amp;quot;doing SQL&amp;quot; for years, and I've learned a bunch of new tricks and rediscovered things I had forgoten from reading this.  And not only is it informative on SQL, but it's also entertaining and informative on other subjects (e.g., in one chapter, Joe describes the history of the soundex algorithm).&lt;/p&gt;&lt;p&gt;The problem with getting more SQL-literate is that I have to work with MySQL.  Now, I don't want to rag on MySQL too much - it's good &lt;em&gt;for what it is&lt;/em&gt;.  And what it is is an engine for storing data and getting it back out in an efficient manner.  The problem is that it's really not focused on implementing standard SQL in any deep way.  &lt;/p&gt;&lt;p&gt;My particular annoyance today came when I was writing code to do a simple update.  The situation is that I was working on a new variation on the picture galleries for our site, and realized that I wasn't associating a thumbnail image with the galleries I was creating.  By virtue of the way our codebase works (all of which pre-dates my involvement), our picture galleries consist of &lt;em&gt;n+1&lt;/em&gt; rows in our main media table, where &lt;em&gt;n&lt;/em&gt; is the number of pictures in the gallery - one row per picture and another row for the gallery meta-item.  Because of the way I had written my creation methods in PHP and added my foreign key constraints in the database, the path of least resistance was to just set the gallery thumbnail to the same value as one of the pictures.  Here's a simplified example of the basic query I used:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;-- Create a sample test and populate it with data.&lt;br /&gt;CREATE TABLE test_tbl (id INT, val2 INT);&lt;br /&gt;INSERT INTO test_tbl VALUES (1, 2);&lt;br /&gt;INSERT INTO test_tbl VALUES (3, NULL);&lt;br /&gt;-- Here's the query I was running.&lt;br /&gt;UPDATE test_tbl SET val2 = (SELECT val2 FROM test_tbl WHERE id = 3) WHERE id=2;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;In the routine as I had written it, I had the IDs of the gallery and all the pictures, but that was it.  With a query like this, I could just clone the thumbnail of one picture to the gallery in a single query - no need to clutter the code with any lookups or suchlike.  &lt;/p&gt;&lt;p&gt;Of course, if you know MySQL, you may already know that this didn't work.  When I  tried running this, I got:&lt;br /&gt;&lt;code&gt;ERROR 1093 (HY000): You can't specify target table 'test_tbl' for update in FROM clause&lt;/code&gt;&lt;br /&gt;I was actually kind of surprised by this.  I mean, this query isn't all that exotic.  It's perfectly valid in standard SQL and it works in PostgreSQL.  Why not MySQL?&lt;/p&gt;&lt;p&gt;Well, the answer seems to be that MySQL disregards the conceptual execution model of subqueries.  I say this because, if you do the subquery on &lt;em&gt;a different table than the one being updated&lt;/em&gt;, then MySQL doesn't have a problem with it.  Example:&lt;code&gt;&lt;br /&gt;-- Create a second table and add a row.&lt;br /&gt;CREATE TABLE extra_tbl (id INT, val2 INT);&lt;br /&gt;INSERT INTO test_tbl VALUES (3, 9);&lt;br /&gt;-- This one works just find in MySQL.&lt;br /&gt;UPDATE test_tbl SET val2 = (SELECT val2 FROM extra_tbl WHERE id = 3) WHERE id=2;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You see, according to Joe Celko (read the book!), the execution model of a subquery is that it creates a temporary table.  So, in the case of my first sample query, it would create a copy of test_tbl, find the target row in that, and then update test_tbl.  If you didn't use that model, then it would make some sense that you can't update the same table you're searching in.  (Note: Of course, other databases don't &lt;em&gt;actually&lt;/em&gt; create temporary tables for every subquery - they just produce the same result as if they did.)&lt;/p&gt;&lt;p&gt;I guess my problem is that I'm just starting to expect too much from MySQL.  I've reached the point that I find it annoying that the default storage engine (MyISAM) doesn't support foreign key constraints.  I find it even more annoying that MySQL doesn't support the enormously useful CHECK constraints at all.  And, really, is it absolutely necessary to invent new versions of standard functions, mangle standard functions (what the hell did they do to CAST()?), or to disable the ANSI string concatenation operator by default?  It all just just seems superfluous.  After all, PostgreSQL didn't have much trouble with the ANSI standard.  Why can't MySQL get it?&lt;/p&gt;&lt;p&gt;Oh, well.  I guess it could be worse.  At least now I have the wisdom to know what I'm missing.  In days gone by, I thought MS Access seemed just fine as a database.  Back then, I didn't declare primary keys and didn't even know what indexes were!  By comparison to that, MySQL looked like freakin' Oracle!  If only I hadn't been so young and stupid then, think of where I'd be now....&lt;/p&gt;
</description>
<author>pageer@skepticats.com (Peter Geer)</author>
<comments>http://linlog.skepticats.com/entries/2008/06/05_2303/comments/</comments>
<guid>http://linlog.skepticats.com/entries/2008/06/05_2303/</guid>
</item>
</channel>
</rss>