<?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>smufflersWorld &#187; MySQL</title>
	<atom:link href="http://smufflersworld.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://smufflersworld.com</link>
	<description>my life online . . .</description>
	<lastBuildDate>Fri, 16 Dec 2011 14:38:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Tell me about yourself . . .</title>
		<link>http://smufflersworld.com/2009/09/tell-me-about-yourself/</link>
		<comments>http://smufflersworld.com/2009/09/tell-me-about-yourself/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 14:14:35 +0000</pubDate>
		<dc:creator>jodrell</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://smufflersworld.com/?p=345</guid>
		<description><![CDATA[A little while ago MySQL introduced Stored Procedures thereby, in some peoples eyes, making it a &#8216;proper&#8217; database (clearly a load of rubbish as it was totally fit for purpose anyway but that&#8217;s another argument). For security reasons if you DROP a stored procedure in MySQL any grants to use it are also removed. This [...]]]></description>
			<content:encoded><![CDATA[<p>A little while ago MySQL introduced Stored Procedures thereby, in some peoples eyes, making it a &#8216;proper&#8217; database (clearly a load of rubbish as it was totally fit for purpose anyway but that&#8217;s another argument).</p>
<p>For security reasons if you DROP a stored procedure in MySQL any grants to use it are also removed. This makes perfect sense as stored procedures can be set to run internally as a different user that the one that called it. If the GRANT wasn&#8217;t removed it would be possible to have a perfectly innocent procedure removed and, a while later a new one added that happened to have the same name (I know that this would require a deal of disorganisation but hey) that could drop the whole DB. The user who had access to the first procedure would then have access to the new one (bad times).</p>
<p>While it makes sense that the GRANT is removed when the stored procedure is removed it doesn&#8217;t really make sense that you can&#8217;t update stored procedures, you have to drop and recreate them, thereby losing all the grants applicable to them every time &#8211; damn annoying</p>
<p>The solution . . .<span id="more-345"></span>The solution is to make sure you get all of the applicable grants ready to put back into the database before you drop the stored procedure. However, unless you&#8217;re very organised (I&#8217;m not) or you have a limited number of DB users to manually check (we don&#8217;t) this can be a bit of a pain.</p>
<p>MySQL stores all the information about a users GRANTs and PRIVILEGEs in a database called mysql so rather than doing all those lookups manually and possibly missing something, why not just get the server to tell you who it thinks has access to what. To find all of the users (user/host pairs obviously) that have access to execute a procedure called procedureName in the database dbName you can use this query.</p>
<blockquote><p>select User, Host FROM mysql.procs_priv WHERE Routine_name=&#8217;procedureName&#8217; AND Db=&#8217;dbName&#8217;;</p></blockquote>
<p>Which is great, but it does mean that you&#8217;re still going to have to rewrite all the queries to put those grants back in . . . why not use CONCAT to have the query output the finished queries for you??</p>
<blockquote><p>select CONCAT(&#8216;GRANT &#8216;, Proc_priv, &#8216; ON PROCEDURE `&#8217;, Db, &#8216;`.`&#8217;, Routine_name, &#8216;` TO `&#8217;, User, &#8216;`@`&#8217;, Host, &#8216;`;&#8217;) FROM mysql.procs_priv WHERE Routine_name=&#8217;procedureName&#8217; AND Db=&#8217;dbName&#8217;;</p></blockquote>
<p>Bingo . . . just run this before you are going to DROP a stored procedure and you can add it&#8217;s output onto the end of the stored procedure script.  That way it&#8217;ll add the relevant grants straight back in <img src='http://smufflersworld.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://smufflersworld.com/2009/09/tell-me-about-yourself/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How old are you???</title>
		<link>http://smufflersworld.com/2009/09/how-old-are-you/</link>
		<comments>http://smufflersworld.com/2009/09/how-old-are-you/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 11:12:05 +0000</pubDate>
		<dc:creator>jodrell</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://smufflersworld.com/?p=313</guid>
		<description><![CDATA[Everyone knows how old they are, right?? Well OK, so sometimes I have to think about it a couple of times just to check (what with it nearly being my birthday) but still, it&#8217;s pretty easy. However if you&#8217;re a database without a function to find out age it&#8217;s a tad more tricky. This just [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone knows how old they are, right?? Well OK, so sometimes I have to think about it a couple of times just to check (what with it nearly being my birthday) but still, it&#8217;s pretty easy.</p>
<p>However if you&#8217;re a database without a function to find out age it&#8217;s a tad more tricky.</p>
<p>This just came up as someone in the office was writing a report that included calculating the users ages . . . the solution they used was good enough for our purposes but was also one of those little things that bugs you because you know there&#8217;s a better way to do it.</p>
<p>The initial solution was as follows . . . btw, let&#8217;s also chuck the date of birth into a variable to simplify the queries <img src='http://smufflersworld.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<blockquote><p>SET @dateOfBirth=&#8217;1972-10-03&#8242;;</p>
<p>SELECT (DATEDIFF(NOW(), @dateOfBirth))/365;</p></blockquote>
<p><span id="more-313"></span>As I said it&#8217;ll work but obviously there are going to be cases when it&#8217;s not quite right. The problem is obviously caused by the number of days in a year being inconsistent. Now MySQL has plenty of <a href="http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html" target="_blank">date functions</a> built into it that we can leverage here so let&#8217;s see what we can come up with.</p>
<p>In order to get some more precision I first thought to convert the period from DOB to now into seconds . . .</p>
<blockquote><p>SELECT datediff(NOW(), @dateOfBirth)*24*60*60;</p></blockquote>
<p>We can then convert that back to a date since epoch using,</p>
<blockquote><p>SELECT from_unixtime((datediff(NOW(), @dateOfBirth))*24*60*60);</p></blockquote>
<p>then we rip the year out of that newly created date and take 1970 away from it to get the final age . . .</p>
<blockquote><p>SELECT date_format(from_unixtime((datediff(NOW(), @dateOfBirth))*24*60*60), &#8216;%Y&#8217;)-1970;</p></blockquote>
<p>BINGO . . . err, oopsie . . . that ain&#8217;t gonna work for anyone born before the epoch is it (because the from_unixtime function will return NULL for any negative values passed to it).  As usual I&#8217;ve gone off in the first direction I&#8217;d thought of and not bothered th check things out on the way.  Deep breath time and start again then . . .</p>
<p>Let&#8217;s start simple,</p>
<blockquote><p>SELECT YEAR(CURRENT_DATE()) &#8211; YEAR(@dateOfBirth);</p></blockquote>
<p>That&#8217;ll work fine as long as the month/day of the birthday has already been passed during the current year, if it hasn&#8217;t we need to take one away (eugh, sounds hacky again). To find if we&#8217;ve passed that date we can use,</p>
<blockquote><p>SELECT date_format(CURRENT_DATE(), &#8216;%m-%y&#8217;)&lt;date_format(@dateOfBirth, &#8216;%m-%y&#8217;);</p></blockquote>
<p>and then putting it all together,</p>
<blockquote><p>SELECT YEAR(CURRENT_DATE()) &#8211; YEAR(@dateOfBirth) &#8211; (date_format(CURRENT_DATE(), &#8216;%m-%y&#8217;)&lt;date_format(@dateOfBirth, &#8216;%m-%y&#8217;)) AS age;</p></blockquote>
<p>Well . . . it works but I know there must be a simpler way to do it &#8211; I&#8217;ll have another look later when I&#8217;m not in the office but at least this woodpecker has been put to bed for now!</p>
]]></content:encoded>
			<wfw:commentRss>http://smufflersworld.com/2009/09/how-old-are-you/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

