<?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>A Little Noise</title>
	<atom:link href="http://thenoyes.com/littlenoise/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://thenoyes.com/littlenoise</link>
	<description></description>
	<lastBuildDate>Wed, 25 Aug 2010 16:07:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Multi-master replication</title>
		<link>http://thenoyes.com/littlenoise/?p=117</link>
		<comments>http://thenoyes.com/littlenoise/?p=117#comments</comments>
		<pubDate>Wed, 25 Aug 2010 14:35:12 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=117</guid>
		<description><![CDATA[Implement multi-master to single-slave replication by periodically saving state and changing masters, and do it all in SQL.* Just a proof of concept. I suggest you add some error checking (like, don't make the switch if the slave isn't running). Remember that all this stuff goes on the SLAVE. If you absent-mindedly log in to [...]]]></description>
			<content:encoded><![CDATA[<p>Implement multi-master to single-slave replication by periodically saving state and changing masters, and do it all in SQL.*</p>
<p>Just a proof of concept. I suggest you add some error checking (like, don't make the switch if the slave isn't running).</p>
<p>Remember that all this stuff goes on the SLAVE. If you absent-mindedly log in to the master, like I did a few times, you might wonder why your relay_log.info file isn't read.</p>
<p>Set up a table to keep track of each master file. Mine use the same user name and password for all hosts; you can add those fields and adjust the procedure accordingly if you like.</p>
<p><code>USE mysql;<br />
DROP TABLE IF EXISTS rotate_master;<br />
CREATE TABLE rotate_master (<br />
  id int auto_increment primary key,<br />
  master_host varchar(255),<br />
  master_port int unsigned,<br />
  master_log_file varchar(255),<br />
  master_log_pos int unsigned,<br />
  in_use boolean DEFAULT 0<br />
);</code></p>
<p>Insert the list of masters. The one that is currently master should have `in_use` set to 1; all the others should be 0. The order you insert them is the order they will rotate.</p>
<p><code>INSERT INTO rotate_master VALUES (NULL, 'localhost', 3306, 'bin.000001', 0, 1);<br />
INSERT INTO rotate_master VALUES (NULL, 'localhost', 3308, 'bin.000001', 0, 0);</code></p>
<p>Then, a procedure to grab the current position (by reading from the relay_log.info file, since the slave position is not otherwise exposed in any accessible manner), record it in the above table, and change masters to the next one in the list.</p>
<p><code>DROP PROCEDURE IF EXISTS rotate_master;<br />
DELIMITER //</p>
<p>CREATE PROCEDURE rotate_master()<br />
BEGIN<br />
  DECLARE _info text;<br />
  DECLARE _master_file varchar(255);<br />
  DECLARE _master_pos int unsigned;<br />
  DECLARE _master_host varchar(255);<br />
  DECLARE _master_port int unsigned;<br />
  DECLARE _id int;</p>
<p>  STOP SLAVE;</p>
<p>  -- fetch and store current position<br />
  SELECT LOAD_FILE(@@relay_log_info_file) INTO _info;<br />
  SELECT<br />
    SUBSTRING_INDEX(SUBSTRING_INDEX(_info, '\n', 3), '\n', -1),<br />
    SUBSTRING_INDEX(SUBSTRING_INDEX(_info, '\n', 4), '\n', -1)<br />
  INTO _master_file, _master_pos;<br />
  UPDATE mysql.rotate_master SET master_log_file = _master_file, master_log_pos = _master_pos, id = LAST_INSERT_ID(id) WHERE in_use = 1;</p>
<p>  -- fetch next host<br />
  SELECT<br />
    id,<br />
    master_host,<br />
    master_port,<br />
    master_log_file,<br />
    master_log_pos<br />
  INTO _id, _master_host, _master_port, _master_file, _master_pos<br />
  FROM rotate_master<br />
  ORDER BY id <= LAST_INSERT_ID(), id LIMIT 1;</p>
<p>  -- advance to next host<br />
  SET @sql := CONCAT(<br />
    'CHANGE MASTER TO master_host=', QUOTE(_master_host),<br />
    ', master_port=', _master_port,<br />
    ', master_log_file=', QUOTE(_master_file),<br />
    ', master_log_pos=', _master_pos);</p>
<p>  PREPARE myStmt FROM @sql;<br />
  EXECUTE myStmt;</p>
<p>  -- mark host as changed<br />
  UPDATE mysql.rotate_master SET in_use = 0 WHERE in_use = 1;<br />
  UPDATE mysql.rotate_master SET in_use = 1 WHERE id = _id;</p>
<p>  START SLAVE;<br />
END//</p>
<p>DELIMITER ;</code></p>
<p>Finally, schedule it to rotate. I used 10 seconds just to play with; I imagine a few minutes would be more practical. *If you don't have 5.1 or later, you'll have to schedule this part externally, with cron or task scheduler.</p>
<p><code>DROP EVENT IF EXISTS rotate_master;<br />
CREATE EVENT rotate_master<br />
  ON SCHEDULE EVERY 10 SECOND<br />
  DO CALL mysql.rotate_master();</code></p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=117</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>LOAD DATA and recovery</title>
		<link>http://thenoyes.com/littlenoise/?p=104</link>
		<comments>http://thenoyes.com/littlenoise/?p=104#comments</comments>
		<pubDate>Wed, 24 Mar 2010 17:39:08 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL Gotchas]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=104</guid>
		<description><![CDATA[A little two-part quiz. If you get the first one without peeking, you're worth your pay as a DBA. If you get the second one without peeking, you may tell your boss that some random guy on the Internet says you deserve a raise. Start with a text file, 'test.txt', with these three lines: 1 [...]]]></description>
			<content:encoded><![CDATA[<p>A little two-part quiz. If you get the first one without peeking, you're worth your pay as a DBA. If you get the second one without peeking, you may tell your boss that some random guy on the Internet says you deserve a raise.</p>
<p>Start with a text file, 'test.txt', with these three lines:</p>
<p><code>1<br />
1<br />
2</code></p>
<p>Set up the test in MySQL:</p>
<p><code>DROP TABLE IF EXISTS t1;<br />
CREATE TABLE t1 (id int primary key);<br />
LOAD DATA INFILE 'test.txt' INTO TABLE t1;</code></p>
<p><span id="more-104"></span></p>
<p>This gives "<code>ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'</code>", which is expected. </p>
<p>What's in the table? </p>
<p><a href='javascript:void(null);' onclick="s_toggleDisplay(document.getElementById('SID937118878'), this, 'Show Answer &#9660;', 'Hide Answer &#9650;');">Show Answer &#9660;</a></p>
<div id='SID937118878' style='display:none;'>
It depends. If the engine is MyISAM, then you'll have one row: the first '1' from the file was inserted, everything else was skipped. If the engine is InnoDB, you'll have no rows, because the transaction would rollback. So either 1 row or 0 rows.
</div>
<p>Now, pretend you're setting up a slave, or there was a crash and you're recovering from binary logs:</p>
<p><code>mysqlbinlog bin.000001 | mysql</code></p>
<p>How many rows are in t1 now?</p>
<p><a href='javascript:void(null);' onclick="s_toggleDisplay(document.getElementById('SID780059628'), this, 'Show Answer &#9660;', 'Hide Answer &#9650;');">Show Answer &#9660;</a></p>
<div id='SID780059628' style='display:none;'>
<code><br />
mysql> SELECT * FROM t1;<br />
+----+<br />
| id |<br />
+----+<br />
|  1 |<br />
|  2 |<br />
+----+<br />
2 rows in set (0.00 sec)</code></p>
<p>Why? The manual says, "mysqlbinlog converts LOAD DATA INFILE statements to LOAD DATA LOCAL INFILE statements," and, "with LOCAL, the default duplicate-key handling behavior is the same as if IGNORE is specified."<br />
<a href=" http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html"></p>
<p>http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html</a></p>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/load-data.html">http://dev.mysql.com/doc/refman/5.1/en/load-data.html</a></p>
<p>Note that a replicating slave will handle it correctly - if the master used LOCAL (and therefore IGNORE), the slave will do IGNORE. If the master did not use LOCAL or IGNORE and so got the error above, the slave will do the same, and so the data will match. So be advised: replication and <code>mysqlbinlog | mysql</code> may not give the same results.
</div>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=104</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Restore from mysqldump --all-databases in parallel</title>
		<link>http://thenoyes.com/littlenoise/?p=100</link>
		<comments>http://thenoyes.com/littlenoise/?p=100#comments</comments>
		<pubDate>Thu, 11 Feb 2010 21:12:28 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=100</guid>
		<description><![CDATA[csplit backup.sql /"^-- Current Database"/ {*}; for f in xx*; do cat xx00 "$f" &#124; mysql& done; and then rm xx* when the background jobs have finished. I haven't done any benchmarking, and I haven't worked out what to do if the number of databases exceeds the number of available connections.]]></description>
			<content:encoded><![CDATA[<p><code>csplit backup.sql /"^-- Current Database"/ {*}; for f in xx*; do cat xx00 "$f" | mysql& done;</code></p>
<p>and then <code>rm xx*</code> when the background jobs have finished.</p>
<p>I haven't done any benchmarking, and I haven't worked out what to do if the number of databases exceeds the number of available connections.</p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=100</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>mysql&#8217;s --xml and some XSLT</title>
		<link>http://thenoyes.com/littlenoise/?p=99</link>
		<comments>http://thenoyes.com/littlenoise/?p=99#comments</comments>
		<pubDate>Fri, 29 Jan 2010 18:12:15 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL FAQ]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=99</guid>
		<description><![CDATA[Somebody asked in Freenode the other day how to get their data out of MySQL into a specific XML format. Both mysqldump and the mysql client have --xml options. The output from the cli looks like this: &#60;resultset statement="SELECT here"&#62; &#160;&#160;&#60;row&#62; &#160;&#160;&#160;&#160;&#60;field name="field1"&#62;value&#60;/field&#62; &#160;&#160;&#160;&#160;&#60;field name="field2"&#62;value&#60;/field&#62; &#160;&#160;&#60;/row&#62; &#160;&#160;&#60;row&#62; &#160;&#160;&#160;&#160;&#60;field name="field1"&#62;value&#60;/field&#62; &#160;&#160;&#160;&#160;&#60;field name="field2"&#62;value&#60;/field&#62; &#160;&#160;&#60;/row&#62; &#60;/resultset&#62; I wanted [...]]]></description>
			<content:encoded><![CDATA[<p>Somebody asked in Freenode the other day how to get their data out of MySQL into a specific XML format.</p>
<p>Both mysqldump and the mysql client have <code>--xml</code> options. The output from the cli looks like this:</p>
<p><code>&lt;resultset statement="SELECT here"&gt;<br />
&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;field name="field1"&gt;value&lt;/field&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;field name="field2"&gt;value&lt;/field&gt;<br />
&nbsp;&nbsp;&lt;/row&gt;<br />
&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;field name="field1"&gt;value&lt;/field&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;field name="field2"&gt;value&lt;/field&gt;<br />
&nbsp;&nbsp;&lt;/row&gt;<br />
&lt;/resultset&gt;</code></p>
<p>I wanted to change those &lt;field name="fieldName"&gt; into &lt;fieldName&gt; tags, and all it takes is a little XSLT, which I've uploaded <a href="http://www.thenoyes.com/storage/mysql.xsl">here</a>.</p>
<p>On Linux you can do something like this:</p>
<p><code>mysql -e "SELECT * FROM dbname.tablename" | xsltproc mysql.xsl -</code></p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=99</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Make an ALTER TABLE script with MySQL Workbench</title>
		<link>http://thenoyes.com/littlenoise/?p=98</link>
		<comments>http://thenoyes.com/littlenoise/?p=98#comments</comments>
		<pubDate>Thu, 28 Jan 2010 17:05:27 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=98</guid>
		<description><![CDATA[So you have two versions of a database sitting around - maybe you've been trying things out on your development box, and now you want to move it all over to production. If it's just a new table here and an extra column there, you could do it by hand, but if you've made lots [...]]]></description>
			<content:encoded><![CDATA[<p>So you have two versions of a database sitting around - maybe you've been trying things out on your development box, and now you want to move it all over to production. If it's just a new table here and an extra column there, you could do it by hand, but if you've made lots of changes, it would be nice to let the computer do it for you.</p>
<p>Enter MySQL Workbench.<br />
<span id="more-98"></span><br />
Workbench lets you import the structure from a dump file, or reverse engineer from a running server. Then you can synchronize it with a same-named database on another server, and it will sort out the required CREATE TABLE or ALTER TABLE ADD COLUMN for you. You don't even have to complete the step and actually let it do the synchronization, if all you want is to save the script for reference purposes.</p>
<p><a href=" http://www.screentoaster.com/watch/stWU9dRkBIR19cRFpaW1JQXl5c/workbench_synchronization"><br />
Here's a little screencast</a> showing the action.</p>
<p>I first import the old structure into the MySQL server using the command line client:</p>
<p>mysql < oldTest.sql</p>
<p>I then show connecting to the server to demonstrate that the server holds just two tables, `t1` and `t2`, and that t1 has only a single column, `id`.</p>
<p>Next, I switch to Workbench and import the modified file, newTest.sql. Note that both of the files include the USE dbname; statement so that Workbench knows which schema to use. The new schema includes a new table, `t3`, as well as adding a new column to `t1`, column `d`.</p>
<p>I synchronize the model with the running server, ignoring the `mydb` schema and updating the source for the `test` schema. The resulting script shows the CREATE TABLE statement for `t3`, and the ALTER TABLE statement to add `d` to `t1`. That script can be saved as a file, copied to the clipboard, or executed directly on the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=98</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Trigger on firing table</title>
		<link>http://thenoyes.com/littlenoise/?p=97</link>
		<comments>http://thenoyes.com/littlenoise/?p=97#comments</comments>
		<pubDate>Tue, 26 Jan 2010 22:07:12 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=97</guid>
		<description><![CDATA[CREATE TABLE t1 (id int); CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (NEW.id); That's not allowed; it won't let you create the trigger. CREATE TABLE t1 (id int); CREATE TABLE f1 (id int) ENGINE=FEDERATED CONNECTION='localhost/test/t1'; CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW INSERT INTO f1 [...]]]></description>
			<content:encoded><![CDATA[<pre>
CREATE TABLE t1 (id int);
CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
  INSERT INTO t1 VALUES (NEW.id);
</pre>
<p>That's not allowed; it won't let you create the trigger.</p>
<pre>CREATE TABLE t1 (id int);
CREATE TABLE f1 (id int) ENGINE=FEDERATED CONNECTION='localhost/test/t1';
CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
  INSERT INTO f1 VALUES (NEW.id);</pre>
<p>The server lets that through. Don't do it.</p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=97</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On unions and derivatives</title>
		<link>http://thenoyes.com/littlenoise/?p=95</link>
		<comments>http://thenoyes.com/littlenoise/?p=95#comments</comments>
		<pubDate>Fri, 04 Dec 2009 22:25:33 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=95</guid>
		<description><![CDATA[On occasion I need to generate a number of rows. I don't care about the contents, just how many rows there are. Maybe I want to create a table filled with a sequence of numbers. One common way to do this is to join a bunch of subqueries built out of unions: SET @count := [...]]]></description>
			<content:encoded><![CDATA[<p>On occasion I need to generate a number of rows. I don't care about the contents, just how many rows there are. Maybe I want to create a table filled with a sequence of numbers. One common way to do this is to join a bunch of subqueries built out of unions:</p>
<p><code><br />
SET @count := 0;<br />
INSERT INTO table SELECT @count := @count + 1<br />
FROM (SELECT 1 UNION SELECT 2) a<br />
JOIN (SELECT 1 UNION SELECT 2) b<br />
JOIN (SELECT 1 UNION SELECT 2) c</code><br />
...</p>
<p>Of course, I could union more than two selects (e.g. <code>SELECT 1 UNION SELECT 2 UNION SELECT 3</code>). That makes each derived table longer, but reduces how many must be joined.</p>
<p>Question: What's the optimal size of each derived table?</p>
<p>Defining "optimal": since this is a one-off query, I don't much care about performance (within reason), but I do care about how much typing I have to do. So I will favor "fewer characters" over "fewer joins".</p>
<p>Each derived table in the query takes up 15 * numSelects + 2 characters.</p>
<p>To generate a given number of rows requires CEILING(LOG(numRows) / LOG(numSelects)) derived tables.</p>
<p>If I want 1000 rows in the result, I'd need 10 derived tables of two rows each (320 characters), or 7 of three rows (329 characters), or 3 of ten rows (456 characters).</p>
<p>For any given numRows, what's the minimum of CEILING(LOG(numRows) / LOG(numSelects)) * (15 * numSelects + 2) ?</p>
<p>The answer varies with numRows - 2, 3, or 4 are alternately best when generating less than 130 rows, but any higher than that and the best choice usually turns out to be 3.</p>
<p><code>(SELECT 1 UNION SELECT 2 UNION SELECT 3)</code></p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=95</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>group date</title>
		<link>http://thenoyes.com/littlenoise/?p=94</link>
		<comments>http://thenoyes.com/littlenoise/?p=94#comments</comments>
		<pubDate>Tue, 24 Nov 2009 14:49:34 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=94</guid>
		<description><![CDATA[A non-rigorous, non-scientific, totally off-the-cuff test of which function to pick when you need to group by year and month. I populated a table with 262K rows of random dates, and then ran SELECT %s, COUNT(*) FROM table GROUP BY %s ORDER BY NULL with various functions, which should all result in the same grouping. [...]]]></description>
			<content:encoded><![CDATA[<p>A non-rigorous, non-scientific, totally off-the-cuff test of which function to pick when you need to group by year and month.</p>
<p>I populated a table with 262K rows of random dates, and then ran </p>
<p><code>SELECT %s, COUNT(*) FROM table GROUP BY %s ORDER BY NULL</code></p>
<p>with various functions, which should all result in the same grouping. I repeated each query five times and show the average time, using three different column types DATE, DATETIME, and TIMESTAMP.</p>
<table>
<tr>
<th>expression</th>
<th>DATE</th>
<th>DATETIME</th>
<th>TIMESTAMP</th>
</tr>
<tr>
<td>EXTRACT(YEAR_MONTH FROM d)</td>
<td align='right'>0.362</td>
<td align='right'>0.369</td>
<td align='right'>0.581</td>
</tr>
<tr>
<td>LAST_DAY(d)</td>
<td align='right'>0.374</td>
<td align='right'>0.389</td>
<td align='right'>0.582</td>
</tr>
<tr>
<td>DATE_SUB(d, INTERVAL DAY(d) DAY)</td>
<td align='right'>0.429</td>
<td align='right'>0.882</td>
<td align='right'>1.452</td>
</tr>
<tr>
<td>d - INTERVAL DAY(d) DAY</td>
<td align='right'>0.429</td>
<td align='right'>0.887</td>
<td align='right'>1.535</td>
</tr>
<tr>
<td>SUBSTRING(d, 1, 7)</td>
<td align='right'>0.454</td>
<td align='right'>0.488</td>
<td align='right'>0.719</td>
</tr>
<tr>
<td>YEAR(d), MONTH(d)</td>
<td align='right'>1.046</td>
<td align='right'>1.126</td>
<td align='right'>2.045</td>
</tr>
<tr>
<td>MONTH(d), YEAR(d)</td>
<td align='right'>1.116</td>
<td align='right'>1.196</td>
<td align='right'>2.112</td>
</tr>
<tr>
<td>LEFT(d, 7)</td>
<td align='right'>1.307</td>
<td align='right'>1.405</td>
<td align='right'>2.123</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y%m')</td>
<td align='right'>1.480</td>
<td align='right'>1.565</td>
<td align='right'>2.112</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y-%m')</td>
<td align='right'>1.514</td>
<td align='right'>1.615</td>
<td align='right'>2.564</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m%Y')</td>
<td align='right'>1.517</td>
<td align='right'>1.604</td>
<td align='right'>2.420</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m-%Y')</td>
<td align='right'>1.562</td>
<td align='right'>1.656</td>
<td align='right'>2.465</td>
</tr>
<tr>
<td>MONTHNAME(d), YEAR(d)</td>
<td align='right'>1.613</td>
<td align='right'>1.713</td>
<td align='right'>2.812</td>
</tr>
<tr>
<td>YEAR(d), MONTHNAME(d)</td>
<td align='right'>1.663</td>
<td align='right'>1.766</td>
<td align='right'>2.873</td>
</tr>
</table>
<p>And just in case you want to extract a full date (which really only makes sense for datetime and timestamp):</p>
<table>
<tr>
<th>expression</th>
<th>DATE</th>
<th>DATETIME</th>
<th>TIMESTAMP</th>
</tr>
<tr>
<td>DATE(d)</td>
<td align='right'>0.357</td>
<td align='right'>0.374</td>
<td align='right'>0.591</td>
</tr>
<tr>
<td>EXTRACT(YEAR_MONTH FROM d), EXTRACT(DAY FROM d)</td>
<td align='right'>0.377</td>
<td align='right'>0.407</td>
<td align='right'>0.730</td>
</tr>
<tr>
<td>EXTRACT(DAY FROM d), EXTRACT(YEAR_MONTH FROM d)</td>
<td align='right'>0.395</td>
<td align='right'>0.422</td>
<td align='right'>0.751</td>
</tr>
<tr>
<td>MONTH(d), YEAR(d), DAY(d)</td>
<td align='right'>0.395</td>
<td align='right'>0.426</td>
<td align='right'>0.870</td>
</tr>
<tr>
<td>YEAR(d), DAY(d), MONTH(d)</td>
<td align='right'>0.398</td>
<td align='right'>0.440</td>
<td align='right'>0.862</td>
</tr>
<tr>
<td>YEAR(d), MONTH(d), DAY(d)</td>
<td align='right'>0.406</td>
<td align='right'>0.441</td>
<td align='right'>0.867</td>
</tr>
<tr>
<td>DAY(d), YEAR(d), MONTH(d)</td>
<td align='right'>0.409</td>
<td align='right'>0.444</td>
<td align='right'>0.859</td>
</tr>
<tr>
<td>LEFT(d, 10)</td>
<td align='right'>0.437</td>
<td align='right'>0.487</td>
<td align='right'>0.728</td>
</tr>
<tr>
<td>SUBSTRING_INDEX(d, ' ', 1)</td>
<td align='right'>0.439</td>
<td align='right'>0.475</td>
<td align='right'>0.743</td>
</tr>
<tr>
<td>DAY(d), MONTH(d), YEAR(d)</td>
<td align='right'>0.441</td>
<td align='right'>0.477</td>
<td align='right'>0.901</td>
</tr>
<tr>
<td>MONTH(d), DAY(d), YEAR(d)</td>
<td align='right'>0.442</td>
<td align='right'>0.472</td>
<td align='right'>0.914</td>
</tr>
<tr>
<td>SUBSTRING(d, 1, 10)</td>
<td align='right'>0.460</td>
<td align='right'>0.496</td>
<td align='right'>0.729</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%d%Y%m')</td>
<td align='right'>0.539</td>
<td align='right'>0.571</td>
<td align='right'>0.852</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m%Y%d')</td>
<td align='right'>0.542</td>
<td align='right'>0.570</td>
<td align='right'>0.841</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m%d%Y')</td>
<td align='right'>0.543</td>
<td align='right'>0.572</td>
<td align='right'>0.846</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y%m%d')</td>
<td align='right'>0.544</td>
<td align='right'>0.570</td>
<td align='right'>0.842</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y%d%m')</td>
<td align='right'>0.544</td>
<td align='right'>0.572</td>
<td align='right'>0.843</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%d-%Y-%d')</td>
<td align='right'>0.547</td>
<td align='right'>0.574</td>
<td align='right'>0.848</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%d%m%Y')</td>
<td align='right'>0.549</td>
<td align='right'>0.573</td>
<td align='right'>0.842</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m-%Y-%d')</td>
<td align='right'>0.552</td>
<td align='right'>0.583</td>
<td align='right'>0.869</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y-%m-%d')</td>
<td align='right'>0.558</td>
<td align='right'>0.583</td>
<td align='right'>0.854</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%Y-%d-%m')</td>
<td align='right'>0.569</td>
<td align='right'>0.593</td>
<td align='right'>0.867</td>
</tr>
<tr>
<td>d - INTERVAL HOUR(d) HOUR - INTERVAL MINUTE(d) MINUTE - INTERVAL SECOND(d) SECOND</td>
<td align='right'>0.573</td>
<td align='right'>0.653</td>
<td align='right'>1.249</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%d-%m-%Y')</td>
<td align='right'>0.598</td>
<td align='right'>0.637</td>
<td align='right'>0.920</td>
</tr>
<tr>
<td>DATE_FORMAT(d, '%m-%d-%Y')</td>
<td align='right'>0.601</td>
<td align='right'>0.633</td>
<td align='right'>0.904</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=94</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Drilling a hole in a stainless steel sink</title>
		<link>http://thenoyes.com/littlenoise/?p=93</link>
		<comments>http://thenoyes.com/littlenoise/?p=93#comments</comments>
		<pubDate>Sun, 22 Nov 2009 04:32:25 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[Habitat]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=93</guid>
		<description><![CDATA[I needed to drill a couple of 1" holes in the stainless steel kitchen sink to install a pair of soap and lotion dispensers. The most popular answer online was "use a bi-metal hole saw, low speed, lots of pressure, lots of lubricant." I tried that, and the pilot bit wouldn't even scratch it. I [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to drill a couple of 1" holes in the stainless steel kitchen sink to install a pair of soap and lotion dispensers.</p>
<p>The most popular answer online was "use a bi-metal hole saw, low speed, lots of pressure, lots of lubricant." I tried that, and the pilot bit wouldn't even scratch it.</p>
<p>I happened to have a hammer drill and some 3/8" bits, and those went through ... eventually. So I tried to enlarge it with a 1" hammer drill bit. I got a jagged hole and a burned out hammer drill motor, which I have to ship off for repair now, having used it only three times.</p>
<p>The next most popular answer seemed to be a conduit knockout punch, but that requires a pilot hole of 3/4" (if I could make that, I wouldn't need this punch, now would I?) and Lowe's only carries them in a set of 4 for $150.</p>
<p>Fortunately, the manager appeared and talked me down to a $55 Greenlee step bit. Went home, popped it in my little "backup" drill, and had two nice clean holes in well under ten minutes.</p>
<p>Some tips:</p>
<p>- I bought a Greenlee step drill bit, $55 at Lowe's. They also had an Irwin for $53, but the manager said the Greenlee is twice the quality of the Irwin.<br />
- Measure the hole location every which way you can (remember, you only get one shot at this!), and then make a little starter divot with a hammer and nail or punch so the drill doesn't wander over the surface.<br />
- Don't run the drill at full speed; you will work-harden the sink and dull the bit. If it's smoking, you were going too fast.<br />
- Don't run the drill too slow. Apply firm downward pressure (we're talking "both hands on the drill" firm, not "the combined body weight of you and your cousin Earl" firm.) If you run it too slow or don't press firmly, when you finish one step and drop to the next step, it will gouge two chunks out of the side of the hole and lock the bit in place.<br />
- Use plenty of lubricant. WD-40 is fine; any oil ought to suffice. Spray it on liberally before and during drilling.<br />
- Don't forget to mark on the drill bit where to stop - wrap a piece of masking tape around it at the right height, or you may get to repeat this procedure on a new sink.</p>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=93</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GROUP UNCONCAT</title>
		<link>http://thenoyes.com/littlenoise/?p=92</link>
		<comments>http://thenoyes.com/littlenoise/?p=92#comments</comments>
		<pubDate>Fri, 20 Nov 2009 21:18:24 +0000</pubDate>
		<dc:creator>snoyes</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://thenoyes.com/littlenoise/?p=92</guid>
		<description><![CDATA[Dunno why you'd rather do this in SQL than in your application layer, but if you do, here's one way to turn a delimited string of values back into multiple rows - just the opposite of GROUP_CONCAT: SET @sourceString = 'a,b,c,d,e'; SET @sql = CONCAT('INSERT INTO t VALUES (\\'', REPLACE(@sourceString, ',', '\\'),(\\''), '\\')'); PREPARE myStmt [...]]]></description>
			<content:encoded><![CDATA[<p>Dunno why you'd rather do this in SQL than in your application layer, but if you do, here's one way to turn a delimited string of values back into multiple rows - just the opposite of GROUP_CONCAT:</p>
<pre>SET @sourceString = 'a,b,c,d,e';
SET @sql = CONCAT('INSERT INTO t VALUES (\\'', REPLACE(@sourceString, ',', '\\'),(\\''), '\\')');
PREPARE myStmt FROM @sql;
EXECUTE myStmt;</pre>
<p>Just to show what's going on:</p>
<pre>mysql> SELECT @sql;
+----------------------------------------------------+
| @sql                                               |
+----------------------------------------------------+
| INSERT INTO t VALUES ('a'),('b'),('c'),('d'),('e') |
+----------------------------------------------------+
</pre>
]]></content:encoded>
			<wfw:commentRss>http://thenoyes.com/littlenoise/?feed=rss2&amp;p=92</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
