{"id":4171,"date":"2011-12-02T15:55:32","date_gmt":"2011-12-02T13:55:32","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=4171"},"modified":"2011-12-02T15:55:32","modified_gmt":"2011-12-02T13:55:32","slug":"more-mysql-foreach","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/more-mysql-foreach","title":{"rendered":"More MySQL foreach()"},"content":{"rendered":"<p>In my <a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-foreach\">previous post<\/a> I&#8217;ve shown several generic use cases for <a href=\"http:\/\/common-schema.googlecode.com\/svn\/trunk\/common_schema\/doc\/html\/foreach.html\"><em>foreach()<\/em><\/a>, a new scripting functionality introduced in <a href=\"http:\/\/code.google.com\/p\/common-schema\/\" rel=\"nofollow\">common_schema<\/a>.<\/p>\n<p>In this part I present DBA&#8217;s handy syntax for schema and table operations and maintenance.<\/p>\n<p>Confession: while I love <strong>INFORMATION_SCHEMA<\/strong>&#8216;s power, I just <em>hate<\/em> writing queries against it. It&#8217;s just so much typing! Just getting the list of tables in a schema makes for this heavy duty query:<\/p>\n<blockquote>\n<pre>SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='sakila' AND TABLE_TYPE='BASE TABLE';<\/pre>\n<\/blockquote>\n<p>When a join is involved this really becomes a nightmare. I think it&#8217;s cumbersome, and as result, many do not remember the names and meaning of columns, making for <em>&#8220;oh, I need to read the manual all over again just to get that query right&#8221;<\/em>. Anyway, that&#8217;s my opinion.<\/p>\n<p>A <strong>SHOW TABLES<\/strong> statement is easier to type, but cannot be integrated into a <strong>SELECT<\/strong> query (though <a href=\"http:\/\/code.openark.org\/blog\/mysql\/reading-results-of-show-statements-on-server-side\">we have a partial solution<\/a> for that, too), and besides, when filtering out the views, the <strong>SHOW<\/strong> statement becomes almost as cumbersome as the one on <strong>INFORMATION_SCHEMA<\/strong>.<\/p>\n<p>Which is why <em>foreach()<\/em> offers handy shortcuts to common iterations on schemata and tables, as follows:<\/p>\n<h4>Use case: iterate all databases<\/h4>\n<blockquote>\n<pre>call foreach(<span style=\"color: #808000;\">'schema'<\/span>, <span style=\"color: #003366;\">'CREATE TABLE ${schema}.event(event_id INT, msg VARCHAR(128))'<\/span>);<\/pre>\n<\/blockquote>\n<p>In the above we execute a query on each database. Hmmm, maybe not such a good idea to perform this operation on all databases? Let&#8217;s filter them:<\/p>\n<h4>Use case: iterate databases by name match<\/h4>\n<blockquote>\n<pre>call foreach(<span style=\"color: #808000;\">'schema like wordpress_%'<\/span>, <span style=\"color: #003366;\">'ALTER TABLE ${schema}.wp_posts MODIFY COLUMN comment_author VARCHAR(96) NOT NULL'<\/span>);<\/pre>\n<\/blockquote>\n<p>The above will only iterate my WordPress databases (I have several of these), performing an <strong>ALTER<\/strong> on <strong>wp_posts<\/strong> for each of those databases.<!--more--><\/p>\n<p>I don&#8217;t have to quote the <em>like<\/em> expression, but I can, if I wish to.<\/p>\n<p>I can also use a regular expression match:<\/p>\n<blockquote>\n<pre>call foreach(<span style=\"color: #808000;\">'schema ~ \/^wordpress_[0-9]+$\/'<\/span>, <span style=\"color: #003366;\">'ALTER TABLE ${schema}.wp_posts MODIFY COLUMN comment_author VARCHAR(96) NOT NULL'<\/span>);<\/pre>\n<\/blockquote>\n<h4>Use case: iterate tables in a specific schema<\/h4>\n<p>Time to upgrade our <strong>sakila<\/strong> tables to InnoDB&#8217;s compressed format. We use <strong>$()<\/strong>, a synonym for <em>foreach()<\/em>.<\/p>\n<blockquote>\n<pre>call $(<span style=\"color: #808000;\">'table in sakila'<\/span>, <span style=\"color: #003366;\">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB ROW_FORMAT=COMPRESSED'<\/span>);<\/pre>\n<\/blockquote>\n<p>The above will iterate on tables in <strong>sakila<\/strong>. I say <em>tables<\/em>, since it will avoid iterating views (there is still no specific syntax for views iteration). This is done on purpose, as my experience shows there is very little in common between tables and views when it comes to maintenance and operations.<\/p>\n<h4>Use case: iterate tables by name match<\/h4>\n<p>Here&#8217;s a interesting scenario: you wish to work on all tables matching some name. The naive approach would be to:<\/p>\n<blockquote>\n<pre>SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'wp_posts' AND TABLE_TYPE = 'BASE TABLE'<\/pre>\n<\/blockquote>\n<p><em><strong>Wait!<\/strong><\/em> Are you aware this may bring your server down? This query will open all databases at once, opening all <strong>.frm<\/strong> files (though thankfully not data files, since we only check for name and type).<\/p>\n<p>Here&#8217;s a better approach:<\/p>\n<blockquote>\n<pre>call foreach(<span style=\"color: #808000;\">'table like wp_posts'<\/span>, <span style=\"color: #003366;\">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB'<\/span>);<\/pre>\n<\/blockquote>\n<p>(There&#8217;s now FULLTEXT to InnoDB, so the above can make sense in the near future!)<\/p>\n<p>The good part is that <em>foreach()<\/em> will look for matching tables <em>one database at a time<\/em>. It will iterate the list of database, then look for matching tables per database, thereby optimizing the query on <strong>INFORMATION_SCHEMA<\/strong>.<\/p>\n<p>Here, too, I can use regular expressions:<\/p>\n<blockquote>\n<pre>call $(<span style=\"color: #808000;\">'table ~ \/^wp_.*$\/'<\/span>, <span style=\"color: #003366;\">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB'<\/span>);<\/pre>\n<\/blockquote>\n<h4>Conclusion<\/h4>\n<p>This is work in the making, but, as someone who maintains a few productions servers, I&#8217;ve already put it to work.<\/p>\n<p>I&#8217;m hoping the syntax is easy to comprehend. I know that since I developed it it must be far more intuitive to myself than to others. I&#8217;ve tried to keep close on common syntax and concepts from various programming languages.<\/p>\n<p>I would like to get as much feedback as possible. I have further ideas and thoughts on the direction <a href=\"http:\/\/code.google.com\/p\/common-schema\/\">common_schema<\/a> is taking, but wish take it in small steps. Your feedback is appreciated!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post I&#8217;ve shown several generic use cases for foreach(), a new scripting functionality introduced in common_schema. In this part I present DBA&#8217;s handy syntax for schema and table operations and maintenance. Confession: while I love INFORMATION_SCHEMA&#8216;s power, I just hate writing queries against it. It&#8217;s just so much typing! Just getting the [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[53,5],"tags":[67,74,24,57,50,21],"class_list":["post-4171","post","type-post","status-publish","format-standard","hentry","category-development","category-mysql","tag-common_schema","tag-hack","tag-information_schema","tag-open-source","tag-scripts","tag-sql"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-15h","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=4171"}],"version-history":[{"count":33,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4171\/revisions"}],"predecessor-version":[{"id":4525,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4171\/revisions\/4525"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=4171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=4171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=4171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}