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

<channel>
	<title>Stillnet Studios &#187; SQL</title>
	<atom:link href="http://www.stillnetstudios.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stillnetstudios.com</link>
	<description>Web development notes and commentary from Ryan Stille</description>
	<lastBuildDate>Tue, 27 Jul 2010 14:40:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySQL losing case in table names</title>
		<link>http://www.stillnetstudios.com/mysql-losing-case-in-table-names/</link>
		<comments>http://www.stillnetstudios.com/mysql-losing-case-in-table-names/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 17:24:13 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=699</guid>
		<description><![CDATA[I had an issue recently when I was working with a couple other developers on a project.  We keep our MySQL database in sync by exporting the database as an SQL script and sharing it in a subversion repository (I wish MS SQL could be this easy!).  Our table names are saved with [...]]]></description>
			<content:encoded><![CDATA[<p>I had an issue recently when I was working with a couple other developers on a project.  We keep our MySQL database in sync by exporting the database as an SQL script and sharing it in a subversion repository (I wish MS SQL could be this easy!).  Our table names are saved with mix case, like &#8220;userFiles&#8221;, but everytime I would export my database the tables would come out all lower case, like &#8220;userfiles&#8221;.</p>
<p>Turns out this is a simple thing to fix, I had to add a line to MySQL&#8217;s config file: <em>my.cnf</em>.  Mine was located at <em>[MySQL installed root]\bin\my.cnf</em>.  The setting that needs to change is lower_case_table_names, I set the value to 2, like this:</p>
<p><code>lower_case_table_names=2</code></p>
<p>If you are interested, here are the different possible values:</p>
<table>
<tbody>
<tr>
<td valign="top"><span class="bold"><strong>Value</strong></span></td>
<td><span class="bold"><strong>Meaning</strong></span></td>
</tr>
<tr>
<td valign="top">0</td>
<td>Table and database names are stored on disk using the lettercase<br />
                specified in the CREATE  TABLE or CREATE DATABASE statement. Name comparisons are case<br />
                sensitive. Note that if you force this variable to 0 with &#8211;lower-case-table-names=0<br />
                on a case-insensitive file system and access MyISAM tablenames using different<br />
                lettercases, index corruption may result.</td>
</tr>
<tr>
<td valign="top">1</td>
<td>Table names are stored in lowercase on disk and name comparisons are not<br />
                case sensitive. MySQL converts all table names to<br />
                lowercase on storage and lookup. This behavior also<br />
                applies to database names and table aliases.</td>
</tr>
<tr>
<td valign="top">2</td>
<td>Table and database names are stored on disk using the lettercase<br />
                specified in the CREATE TABLE or CREATE  DATABASE statement, but MySQL converts them to<br />
                lowercase on lookup. Name comparisons are not case sensitive. This works only on file<br />
                systems that are not case sensitive! InnoDB table names are stored in<br />
                lowercase, as for lower_case_table_names=1.</td>
</tr>
</tbody>
</table>
<p>On Windows the default is 1.</p>
<p>More information at <a href="http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html">http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/mysql-losing-case-in-table-names/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A &#8216;MakeDate&#8217; function for MS SQL Server</title>
		<link>http://www.stillnetstudios.com/makedate-function-ms-sql-server/</link>
		<comments>http://www.stillnetstudios.com/makedate-function-ms-sql-server/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 02:14:41 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=361</guid>
		<description><![CDATA[The other day I had a need to be creating dates in a SQL Server SQL statement, made from a few different text fields.  I could not find a function to create a date from these, so I wrote one (with the help of our in house SQL guru).

CREATE FUNCTION [dbo].[MakeDate]
(
	-- Add the parameters [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I had a need to be creating dates in a SQL Server SQL statement, made from a few different text fields.  I could not find a function to create a date from these, so I wrote one (with the help of our in house SQL guru).<br />
<span id="more-361"></span></p>
<pre><code>CREATE FUNCTION [dbo].[MakeDate]
(
	-- Add the parameters for the function here
	@inputYear int, @inputMonth int, @inputDay int
)
RETURNS smalldatetime
AS
BEGIN
	DECLARE @inputMonthStr varchar(2), @inputDayStr varchar(2), @returnDate smalldatetime

	SET @inputMonthStr = Right('0' + cast(@inputMonth as varchar(2)),2)
	SET @inputDayStr = Right('0' + cast(@inputDay as varchar(2)),2)

	SET @returnDate = CAST( cast(@inputYear as varchar(4)) + @inputMonthStr + @inputDayStr as smalldatetime)

	-- Return the result of the function
	RETURN @returnDate

END</code></pre>
<p>If you are using MySQL, you already have a create date function built in: <a href="http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_makedate">http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_makedate</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/makedate-function-ms-sql-server/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A bug with Query of Query and * ?</title>
		<link>http://www.stillnetstudios.com/query-of-query-bug/</link>
		<comments>http://www.stillnetstudios.com/query-of-query-bug/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 00:32:03 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=291</guid>
		<description><![CDATA[There may be something buggy here, or maybe I&#8217;m misunderstanding how this should work.
This code executes fine:
&#60;cfquery name="qryListings" dbtype="query"&#62;
SELECT 1 as OrdBy, * FROM qryListings
UNION
SELECT 2 as OrdBy, * FROM qryListingsTmp
ORDER BY OrdBy
&#60;/cfquery&#62;
But when I add a WHERE clause to the second part to filter out records that were in the first group:
&#60;cfquery name="qryListings" dbtype="query"&#62;
SELECT [...]]]></description>
			<content:encoded><![CDATA[<p>There may be something buggy here, or maybe I&#8217;m misunderstanding how this should work.</p>
<p>This code executes fine:</p>
<pre><code>&lt;cfquery name="qryListings" dbtype="query"&gt;
SELECT 1 as OrdBy, * FROM qryListings
UNION
SELECT 2 as OrdBy, * FROM qryListingsTmp
ORDER BY OrdBy
&lt;/cfquery&gt;</code></pre>
<p>But when I add a WHERE clause to the second part to filter out records that were in the first group:</p>
<pre><code>&lt;cfquery name="qryListings" dbtype="query"&gt;
SELECT 1 as OrdBy, * FROM qryListings
UNION
SELECT 2 as OrdBy, * FROM qryListingsTmp WHERE ref_num NOT IN
(#ValueList(qryListings.ref_num)#)
ORDER BY OrdBy
&lt;/cfquery&gt;</code></pre>
<p> I get a ColdFusion error about the number of columns being different between the two queries.<br />
<img src="http://www.stillnetstudios.com/wp-content/uploads/2009/01/qoq_error.png" alt="" title="query of query error" width="435" height="170" class="alignnone size-full wp-image-292" /></p>
<p><span id="more-291"></span><br />
The error goes away if I list out the individual columns, instead of using an asterisk.  This would not work very well in my case, since I don&#8217;t have any control over the query being returned to me and it could be changed without regard to this code.  Thankfully I&#8217;m on CF8 and was able to dynamically grab the column names.</p>
<pre><code>&lt;cfquery name="qryListings" dbtype="query"&gt;
SELECT 1 as OrdBy, #ArrayToList(qryListingsTmp.GetColumnNames())# FROM qryListings
UNION
SELECT 2 as OrdBy, #ArrayToList(qryListingsTmp.GetColumnNames())# FROM qryListingsTmp WHERE ref_num NOT IN
(#ValueList(qryListings.ref_num)#)
ORDER BY OrdBy
&lt;/cfquery&gt;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/query-of-query-bug/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ColdFusion / MySQL Error: Cannot convert value &#8216;0000-00-00 00:00:00&#8242; from column X to TIMESTAMP.</title>
		<link>http://www.stillnetstudios.com/coldfusion-convert-value-from-column-timestamp/</link>
		<comments>http://www.stillnetstudios.com/coldfusion-convert-value-from-column-timestamp/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 01:14:14 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=214</guid>
		<description><![CDATA[I ran into this issue when adding a new datetime column to an existing table in my MySQL 5 database.  I did not get the error in my production environment, only the dev environment on my local machine.

I was puzzled by this error, because I thought the all zeros value basically meant a null/unknown [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into this issue when adding a new datetime column to an existing table in my MySQL 5 database.  I did not get the error in my production environment, only the dev environment on my local machine.</p>
<p><img src="http://www.stillnetstudios.com/wp-content/uploads/2008/11/mysql_error_screenshot.png" alt="" title="mysql error screenshot" width="500" height="78" class="alignnone size-full wp-image-215" /></p>
<p>I was puzzled by this error, because I thought the all zeros value basically meant a null/unknown date value.  Also I wasn&#8217;t using a type TIMESTAMP, I was using a DATETIME column type, so that threw me, too.  After digging through the data a little bit, I found that the values for these new columns in the production database were NULL, but the values in my dev database were &#8216;0000-00-00 00:00:00&#8242;.  A little googling told me that the all zeros value is what happens when an invalid date is assigned to a datetime field.</p>
<p>I could not see any differences in the schema, so I&#8217;m not sure how this happened.  But updating my dev data to be NULL where the value was &#8216;0000-00-00 00:00:00&#8242; solved the problem.</p>
<p>The <em>other</em> option, if you can&#8217;t change your data, is to add these items to your connection string value in the ColdFusion Administrator for your datasource:</p>
<p><code>noDatetimeStringSync=true&amp;zeroDateTimeBehavior=convertToNull</code></p>
<p><img src="http://www.stillnetstudios.com/wp-content/uploads/2008/11/dsn_screenshot.png" alt="" title="mysql connection string screenshot" width="481" height="404" class="alignnone size-full wp-image-216" style="border: 1px solid gray;" /></p>
<p>This tells MySQL to return a null instead of throwing an exception when one of these values is found.  This is how I initially solved the problem, until I figured out that &#8216;0000-00-00 00:00:00&#8242; was not a proper value.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/coldfusion-convert-value-from-column-timestamp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant pagination with MS SQL 2005</title>
		<link>http://www.stillnetstudios.com/pagination-mssql-2005/</link>
		<comments>http://www.stillnetstudios.com/pagination-mssql-2005/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 21:56:59 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=188</guid>
		<description><![CDATA[I&#8217;ve never found a great solution for pagination in SQL 2000.  I much prefer MySQL&#8217;s syntax: SELECT * FROM table LIMIT 100,10.  That will get you 10 records starting at the 100th record.  Why MS SQL still doesn&#8217;t offer an opposite to TOP, I don&#8217;t know.  Yes, I&#8217;ve seen the double [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve never found a great solution for pagination in SQL 2000.  I much prefer MySQL&#8217;s syntax: <code>SELECT * FROM table LIMIT 100,10</code>.  That will get you 10 records starting at the 100th record.  Why MS SQL still doesn&#8217;t offer an opposite to TOP, I don&#8217;t know.  Yes, I&#8217;ve seen the double TOP method where you sort your data twice to end up with the last X rows.  It works, but its not exactly elegant.</p>
<p>But I have come across a new method for pagination using some new 2005 features that is pretty neat.  What I <em>really</em> like about this solution is that it gives you a count of the total number of records, which you usually don&#8217;t get with other pagination methods.<br />
<span id="more-188"></span></p>
<pre><code>SELECT TOP #Val(arguments.maxRows)# * FROM
	(
	SELECT ROW_NUMBER() OVER (ORDER BY <em>your sort order here</em>) AS RowNumber, *, TotalRows=Count(*) OVER()
	FROM <em>tableName</em> WHERE <em>your criteria here</em>
	) _tmpInlineView
WHERE RowNumber &gt;= &lt;cfqueryparam value="#Arguments.startRow#"&gt;
ORDER BY <em>your sort order here</em></code></pre>
<p>This works great, is fast, and as a bonus includes the total number of rows!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/pagination-mssql-2005/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Finding and deleting dupliates from a database table</title>
		<link>http://www.stillnetstudios.com/finding-database-dupliates-jason-troy/</link>
		<comments>http://www.stillnetstudios.com/finding-database-dupliates-jason-troy/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 18:12:07 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/?p=142</guid>
		<description><![CDATA[My SQL savvy coworker Jason Troy has done some work recently on finding and deleting duplicate records in a database.  One of the things he had to do was compare on a text field (that is, over 8000 characters and not a varchar).  Very interesting.
http://phillyun.blogspot.com/2008/10/power-of-sql-find-and-delete-duplicates.html
]]></description>
			<content:encoded><![CDATA[<p>My SQL savvy coworker Jason Troy has done some work recently on finding and deleting duplicate records in a database.  One of the things he had to do was compare on a <em>text </em>field (that is, over 8000 characters and not a varchar).  Very interesting.</p>
<p><a href="http://phillyun.blogspot.com/2008/10/power-of-sql-find-and-delete-duplicates.html">http://phillyun.blogspot.com/2008/10/power-of-sql-find-and-delete-duplicates.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/finding-database-dupliates-jason-troy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problems connecting to MySQL locally &#8211; try localhost instead of %</title>
		<link>http://www.stillnetstudios.com/problems-connecting-to-mysql-locally/</link>
		<comments>http://www.stillnetstudios.com/problems-connecting-to-mysql-locally/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 22:19:05 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/2008/08/24/problems-connecting-to-mysql-locally/</guid>
		<description><![CDATA[I&#8217;m setting up mysql locally on my laptop this weekend, and ran into a snag that cost me at least an hour.  To mimic a web app I am running locally, I needed to connect to mysql with a specific username and password.  But no matter what I did, I always got this [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m setting up mysql locally on my laptop this weekend, and ran into a snag that cost me at least an hour.  To mimic a web app I am running locally, I needed to connect to mysql with a specific username and password.  But no matter what I did, I always got this error:</p>
<pre><code>MySQL: access denied for user: <em>username</em> (Using password: YES)</code></pre>
<p>I got this when connecting via the command line client and via ColdFusion.  Finally after some googling I came across <a href="http://javafoo.wordpress.com/2005/06/30/mysql-access-denied-for-user-using-password-yes">this blog post</a> suggesting to change the privilege details to allow connecting from &#8216;localhost&#8217; instead of &#8216;%&#8217;.   The % indicates a wildcard and should allow connections from any host.  But for some reason this was not working for me.   Changing it to &#8216;localhost&#8217; fixed the problem and allowed me to connect.  I think it may have had something to do with the fact that I checked a box when installing that would only allow connections from the localhost.</p>
<p>I used this SQL to fix the host setting after connecting to the &#8216;mysql&#8217; database:</p>
<pre><code>update user set Host=’localhost’ where User=’myUserName’</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/problems-connecting-to-mysql-locally/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL CASE statement with NULLs</title>
		<link>http://www.stillnetstudios.com/mssql-case-statement-with-nulls/</link>
		<comments>http://www.stillnetstudios.com/mssql-case-statement-with-nulls/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 20:05:28 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/2008/06/04/mssql-case-statement-with-nulls/</guid>
		<description><![CDATA[I&#8217;ve used this trick several times when needing to sort data into groups.  For example say you need to sort car classified listings by price.  Some of the dealers enter a price of &#8220;0&#8243; for their listings.   When sorting by lowest price, you want the listings that actually have a low [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve used this trick several times when needing to sort data into groups.  For example say you need to sort car classified listings by price.  Some of the dealers enter a price of &#8220;0&#8243; for their listings.   When sorting by lowest price, you want the listings that actually have a low price to come first, rather than than the cars costing $0 (hey, I&#8217;d like to buy your free car, thank you).<br />
<span id="more-99"></span></p>
<pre><code>SELECT year, make, model, price,
tmpSortPriceField =
    CASE price
        WHEN 0 THEN 2
        ELSE 1
    END
from cars ORDER BY tmpSortPriceField, price</code></pre>
<p>But I ran into a problem when some of the records had a NULL price.  They were getting a tmpSortPriceField value of 1, because they hit the &#8220;ELSE 1&#8243; part, thus were getting sorted up front.  So I added a line in the CASE statement for the NULL values:</p>
<pre><code>SELECT year, make, model, price,
tmpSortPriceField =
    CASE price
        WHEN 0 THEN 2
        <i>WHEN NULL THEN 2</i>
        ELSE 1
    END
from cars ORDER BY tmpSortPriceField, price</code></pre>
<p>But that didn&#8217;t work, the records with a null price were still getting a tmpSortPriceField value of 1.  I tried using IS NULL and that help either.  I don&#8217;t know why but my null comparison just wasn&#8217;t working.  I finally solved it by changing from the <em>simple case</em> form to the <em>searched case</em> form, where each entry in the case statement is compared for a boolean condition.</p>
<pre><code>SELECT year, make, model, price,
tmpSortPriceField =
    CASE
        WHEN price = 0 THEN 2
        WHEN price IS NULL THEN 2
        ELSE 1
    END
from cars ORDER BY tmpSortPriceField, price</code></pre>
<p>I don&#8217;t know exactly why this works better, but it does seem to handle the NULLs appropriately.  I&#8217;ve also heard from a nearby SQL guru that he always gets better results with the searched case statement, too.</p>
<p>Update &#8211; <a href="http://www.coldfusionmuse.com">Mark Kruger</a> suggested using IsNull may work as well. I tested it, and it does work, but only in SQL Server.  So far the code above will work in MSSQL or MySQL.  Using IsNull() will break in MySQL because the IsNull() function in MySQL is different than the one in MSSQL.  But here is how you would do it using IsNull() in SQL Server:</p>
<pre><code>SELECT year, make, model, price,
tmpSortPriceField =
    CASE <em>IsNull</em>(price,0)
        WHEN 0 THEN 2
        ELSE 1
    END
from cars ORDER BY tmpSortPriceField, price</code></pre>
<p>Update 2 &#8211; <em>BUT</em>, I believe using COALESCE() would work in either MySQL or MSSQL:</p>
<pre><code>SELECT year, make, model, price,
tmpSortPriceField =
    CASE <em>COALESCE</em>(price,0)
        WHEN 0 THEN 2
        ELSE 1
    END
from cars ORDER BY tmpSortPriceField, price</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/mssql-case-statement-with-nulls/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Cleaning up orphaned records in MySQL</title>
		<link>http://www.stillnetstudios.com/cleaning-up-orphaned-records-in-mysql/</link>
		<comments>http://www.stillnetstudios.com/cleaning-up-orphaned-records-in-mysql/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 19:44:58 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/2008/04/11/cleaning-up-orphaned-records-in-mysql/</guid>
		<description><![CDATA[I needed to clean out some orphaned records from a MySQL database today.  I thought this would be as simple as
DELETE FROM subTable WHERE ID IN (
  SELECT subTable.ID from subTable
  LEFT OUTER JOIN parentTable ON subTable.parentID = parentTable.ID
  WHERE  parentTable.ID IS NULL
  )
But this resulted in an error:

ERROR [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to clean out some orphaned records from a MySQL database today.  I thought this would be as simple as</p>
<pre><code>DELETE FROM subTable WHERE ID IN (
  SELECT subTable.ID from subTable
  LEFT OUTER JOIN parentTable ON subTable.parentID = parentTable.ID
  WHERE  parentTable.ID IS NULL
  )</code></pre>
<p>But this resulted in an error:<br />
<span id="more-97"></span><br />
<code>ERROR 1093 (HY000): You can't specify target<br />
table 'subTable' for update in FROM clause</code></p>
<p>In MySQL, you can&#8217;t delete (or update) a table when you are using that table in a subselect.  Here is <em>one</em> work around (I&#8217;m sure there are many):</p>
<pre><code>CREATE TEMPORARY TABLE deleteids AS (
  SELECT subTable.ID from subTable
  LEFT OUTER JOIN parentTable ON subTable.parentID = parentTable.ID
  WHERE  parentTable.ID IS NULL
);

DELETE FROM subTable WHERE ID IN (SELECT ID FROM deleteids);
DROP TABLE deleteids;</code></pre>
<p>If you don&#8217;t explicitly drop your temporary table, it gets dropped automatically when you close your MySQL session.</p>
<p>This worked great for all the tables I needed clean up, except for one.  This table has 150,000 records, with 10,000 of them being abandoned.  The above solution created a query with an IN () statement containing 10,000 values!</p>
<p>Even when I broke it down to running 100 at a time, it was still running about 1 delete per second, and I&#8217;m sure it gets worse if you try to do more than 100 at a time.  MySQL (And SQL Server as well) is not very efficient with IN() clauses.  Thankfully, most (all?) subselects can be rewritten to use a join.  In fact doing this way, I was able to eliminate the temp table.</p>
<pre><code>DELETE subTable FROM subTable LEFT OUTER JOIN parentTable ON
subTable.parentID = parentTable.ID WHERE parentTable.ID IS NULL</code></pre>
<p>This deleted all 10,000 records in two seconds.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/cleaning-up-orphaned-records-in-mysql/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Case sensitive comparisons in SQL</title>
		<link>http://www.stillnetstudios.com/case-sensitive-comparisons-in-sql/</link>
		<comments>http://www.stillnetstudios.com/case-sensitive-comparisons-in-sql/#comments</comments>
		<pubDate>Tue, 03 Jul 2007 15:53:44 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.stillnetstudios.com/2007/07/03/case-sensitive-comparisons-in-sql/</guid>
		<description><![CDATA[We had a need to do a case sensitive SQL comparison this week.  As part of a login process a user is prompted for an answer to their security question.  Now I really don&#8217;t think forcing users to enter their employer&#8217;s name in the exact case does anything to keep out hackers, but [...]]]></description>
			<content:encoded><![CDATA[<p>We had a need to do a case sensitive SQL comparison this week.  As part of a login process a user is prompted for an answer to their security question.  Now I really don&#8217;t think forcing users to enter their employer&#8217;s name in the exact case does anything to keep out hackers, but the client wanted it done this way.</p>
<p>Of course we could pull the values into ColdFusion and do a case sensitive comparison with Compare().  But the code was already setup to do the comparison at the SQL level, which is usually a better idea anyway if it can be done.</p>
<p>There are several ways to tell MS SQL to do a case sensitive comparison. <span id="more-53"></span> One is to convert the values to binary:</p>
<p><code>... WHERE convert(varbinary(255), answer) = convert(varbinary(255), '#Form.answer#')</code></p>
<p>This will not use the index on answer, if there is one.  To make sure SQL Server uses any available indexes, add a normal comparison:</p>
<p><code>... WHERE convert(varbinary(255), answer) = convert(varbinary(255), '#Form.answer#') AND answer = '#Form.answer#'</code></p>
<p>You could also use the BINARY_CHECKSUM function, it will return different results for different case strings:</p>
<p><code>... WHERE BINARY_CHECKSUM(answer) = BINARY_CHECKSUM('#Form.answer#')</code></p>
<p>You&#8217;ll still have the issue with the indexes if you use this method.</p>
<p>Another method, the one I chose to use, is to specify the collation for the values being compared.  Collation refers to a set of rules that determine how data is sorted and compared.  Usually SQL Server is setup to use a case insensitive collation.  We can change that for our comparison:</p>
<p><code>... WHERE answer COLLATE SQL_Latin1_General_CP1_CS_AS = '#Form.answer#' COLLATE SQL_Latin1_General_CP1_CS_AS</code></p>
<p>If you are going to do a lot of case sensitive comparisons against this field, you may want to go into Enterprise Manager and set the  collation for this field from the db default to one that is case sensitive, such as &#8216;SQL_Latin1_General_CP1_CS_AS&#8217;.</p>
<p><img id="image54" src="http://www.stillnetstudios.com/wp-content/uploads/2007/07/collation.png" alt="Setting the collation in SQL Server" /></p>
<p>In MySQL, you can use the BINARY keyword to force a case sensitive comparison:</p>
<p><code>... WHERE answer = BINARY '#Form.answer#'</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.stillnetstudios.com/case-sensitive-comparisons-in-sql/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
