アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

【Flex3】「Flex3の、こんなときどうするの??」

こんにちは、最近モールス信号に興味深々の橋本です。

さて、今回は前回の「AS3のこんなときどうするの?」の続編で、

Flex3のこんなときどうする?」をテーマに、また思いついたところを適当に書いていきたいと思います。

アサインされてるプロジェクトを進める中で発見したものばかりなので、結構偏りがあるかもしれませんが、そこはご了承くださいませ。。。

では、どぞー。

1. スクリプトの中で値をバインドしたい

Q. mxmlの中で値をバインドするときには、バインドしたい変数をmxmlの中で{}で囲み、対象の変数に、[Bindable]タグをつければオッケーなんだけど、スクリプトの中で、値をバインドさせたいときはどうするの??

A. BindingUtilsクラスを使いましょう。
BindingUtils.bindProperty()を使うことで、プロパティ同士をバインドさせることができます。



var textInput:TextInput = new TextInput();
addChild(textInput);
				
var label:Label = new Label();
addChild(label);

BindingUtils.bindProperty(label, "text", textInput, "text");


bindSetterメソッドを使うことで、対象の変数が変化したときに、特定のメソッドを呼び出すこともできますよ。



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
				creationComplete="application1_creationCompleteHandler(event)"
				>
	<mx:TextInput id="textInput"/>
	<mx:Label id="hoge"/>
	<mx:Script>
		<![CDATA[
			import mx.binding.utils.BindingUtils;
			import mx.controls.Label;
			import mx.controls.TextInput;
			import mx.events.FlexEvent;
			

			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				BindingUtils.bindSetter(toUpperCase, this.textInput, "text");
			}
			
			private function toUpperCase(str:String):void
			{
				this.hoge.text = str.toUpperCase();
			}
		]]>
	</mx:Script>
</mx:Application>


2. 自分で作ったクラスのプロパティをバインドの対象にしたい

Q. 自分で作成したクラス内のプロパティをバインドの対象にしたい。でも、呼び出し元で[Bindable]タグをつけるわけにもいかないし、BindingUtils使おうと思っても、対象外って怒られるし、どうするの??

A. 自分で作成したクラス内の変数のセッター内で、イベントをdispatch。Bindableタグの中で、そのイベントを指定するとバインドの対象にできますよ。
こんな感じです。



var hoge:String;

//セッターの中で、設定したイベントをdispatch。Bindableタグで、イベントを指定
[Bindable(event="hogeChange")] 
public function set hoge(value:String):void
{
	dispatchEvent(new Event("hogeChange"));
	hoge = value; 
}


3. 独自イベントをmxmlの選択項目にいれたい

Q. 自分でカスタムしたコンポーネントを呼び出すときに、独自イベントをmxmlで指定したいんだけど、どうするの??

A. コンポーネント内のMetadataタグの中にイベント名を記載しておきましょう。そうすることで、後からmxml上で使うことができます。



<mx:Metadata>
	[Event(name="hoge",type="flash.events.Event")]
</mx:Metadata>


4. DataGridの背景色を変更したい

Q. DataGridの背景色をセル毎に変えたいんだけど、どうするの??

A. DataGridColumnのitemRendererのbackgroundプロパティをtrueにして、backgroundColorを設定することで変更できますよー。



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
				xmlns:components="components.*"
				creationComplete="application1_creationCompleteHandler(event)"
				>
	<mx:DataGrid dataProvider="{dataList}"
				 width="100%"
				 height="100%"
				 >
		<mx:columns>
			<mx:DataGridColumn headerText="hoge" dataField="data" itemRenderer="components.Hoge"/>
		</mx:columns>
	</mx:DataGrid>
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.events.FlexEvent;

			[Bindable]
			private var dataList:ArrayCollection;
			
			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				var arr:ArrayCollection = new ArrayCollection();
				for (var i:int = 0; i < 100; i++)
				{
					var obj:Object =
						{
							data: i
						}
					;
					
					arr.addItem(obj);
				}
				
				dataList = arr;
			}

		]]>
	</mx:Script>
</mx:Application>


itemRenderer用のクラス


package components
{
	import mx.controls.dataGridClasses.DataGridItemRenderer;
	
	public class Hoge extends DataGridItemRenderer
	{
		
		public function Hoge()
		{
			super();
			
			this.background = true;
			// ランダムの色を入れる
			this.backgroundColor = Math.random() * 0xFFFFFF;
		}
	}
}


5. DataGridに文字列以外のものを表示したい

Q. DataGridに、ボタンとか画像とかチェックボックスとか、その他諸々を表示したいんだけど、どうするの??

A. DataGridColumnのitemRendererに、表示したいコンポーネントのクラスを指定することで変更することができますよー。
mxmlで指定するときには、一つ前のサンプルの中でやっているような感じで、クラス名を指定してやればオッケーです。
スクリプトで指定するときには、ClassFactoryクラスのインスタンスを指定してやればオッケーです。



var column:DataGridColumn = new DataGridColumn();
column.itemRenderer = new ClassFactory(Hoge);


6. ツリーに文字列以外のものを表示したい

Q. ツリーにボタンとか画像とかチェックボックスとか、その他諸々を表示したいんだけど、どうするの??

A. DataGridのときと同様に、itemRendererを指定することで可能です。
ただ、チェックボックスを表示するときは要注意。DataGridやTreeなどの、ListベースのコンポーネントのitemRendererは内部で使いまわされるので、チェックした状態を保持しておく機構が必要です。

以下の例では、TreeのdataProviderに指定しているXMLに、selectedというAttributeを持たせて、それを変更することによって、チェック状態を保持しています。



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
				xmlns:components="components.*"
				>
	<mx:Tree itemRenderer="components.Hoge" dataProvider="{xml}" width="100" labelField="@value"/>
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var xml:XMLList = XML(
				<root>
					<node selected="false" value="1"/>
					<node selected="false" value="2"/>
					<node selected="false" value="3"/>
					<node selected="false" value="4"/>
					<node selected="false" value="5"/>
					<node selected="false" value="6"/>
					<node selected="false" value="7"/>
					<node selected="false" value="8"/>
					<node selected="false" value="9"/>
					<node selected="false" value="10"/>
				</root>
			).node;
		]]>
	</mx:Script>
</mx:Application>


チェックボックスを表示するためのカスタムitemRendererクラス


package components
{
	import mx.binding.utils.BindingUtils;
	import mx.controls.CheckBox;
	import mx.controls.treeClasses.TreeItemRenderer;
	import mx.controls.treeClasses.TreeListData;
	
	public class Hoge extends TreeItemRenderer
	{
		[Bindable]
		public var checkBox:CheckBox;
		
		public function Hoge()
		{
			super();
		}
		
		override public function set data(value:Object):void {
			super.data = value;
		}
		
		override protected function createChildren():void{
			super.createChildren();
			
			checkBox = new CheckBox();
			checkBox.setStyle("verticalAlign","middle");
			BindingUtils.bindSetter(setSelected, checkBox, 'selected');
			this.addChild(checkBox);
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {     
			var treeListData:TreeListData = TreeListData(super.listData);
			
			super.updateDisplayList(unscaledWidth,unscaledHeight);
			
			if(super.data)
			{
				if (data.@selected.toString() == 'true')
				{
					checkBox.selected = true;
				}
				else
				{
					checkBox.selected = false;
				}
				
				checkBox.x = super.label.x;
				checkBox.y = ( unscaledHeight - checkBox.height ) /2;
				label.x = checkBox.x + checkBox.width + 20;
			}
		}
		
		private function setSelected(selected:Boolean):void
		{
			if (data)
			{
				data.@selected = selected.toString();
			}
		}
	}
}


7. drag and drop時の画像を変更したい

Q. drag and dropを独自に実装したときに、ドラッグする対象の画像を変更したいんだけど、どうするの??

A. DragManagerクラスのdoDragメソッドの第四引数に画像を指定してやればオッケーです。



DragManager.doDrag(dragInitiator, dragSource, event, img);


8. カーソルを変更したい

Q. 処理待ち中のカーソルを変更したりしたいんだけど、どうするの??

A. cursorManager変数の各種メソッドを使えば可能ですよー。

cursorManager.setBusyCursor()で、デフォルトの時計のアイコンを表示することができます。
cursorManager.removeBusyCursor()で、普通のアイコンに戻せます。

CursorManager.setCursor()を使うことで、独自のアイコンを指定することもできますよー。

9. ラッパーのhtmlのtitleをswfの中で設定したい

Q. htmlのタイトルを変更したいんだけど、どうするの??

A. ExternalInterfaceクラスを使いましょう。そうすることで、swfから、javascriptを実行することができます。



ExternalInterface.call("function(){if(location.href.indexOf('#',0) != -1){document.title = 'hogehoge'}}");


ラッパーhtmlの中でタイトルを最初から指定しておけばいいんじゃネーノ?って思うかもしれませんが、IEだけちゃんと動かないんですよ。なぜか'#'って表示されちゃうんですよね。

10. swfの置いてあるURLを取得したい

Q. swfの実行元のURLを取得して、swfの内部で使いたいんだけど、どうするの??

A. Application.application.urlで、実行されているswfのURLをフルで取得できるので、そこから正規表現で取得しましょう。



private function getHost():String
{
	var fullUrl:String = Application.application.url;
	var reg:RegExp = new RegExp("http://[^/]*/");
	if (reg.test(fullUrl)) {
		return reg.exec(fullUrl).toString();
	}
}


以上でーす。

結構偏った内容なんですが、お役にたてることが一つでもあれば幸いです。
ではではー。

効率よく仕事するためのTIPS(プログラマ編)

こんにちは、牧野です。

突然ですが、

今日の夜はオリオン座流星群がピークをむかえるそうで、多ければ1時間に50個くらい流れ星が見られるとか。ちなみに写真はペルセウス流星群(壁紙Linkより)です。
興味ある人はぜひ夜空を見てみて下さい。


さて、技術ネタを考えていたのですがなかなかいいものが思いつかなかったので、今回は自分がプログラマとして効率よく仕事するために気をつけていること、意識してやっていることをまとめてみました。
仕事では自分の効率を上げるよりも大切なことがたくさんあるので、参考程度に、ということで読んでいただければと思います。


・プログラミングに完全に集中する時間を作る
プログラミングでなくてもそうだと思いますが、集中してやれている時とそうでない時の差は想像以上に大きいものです。
集中する時間を決めたら、その間はメールチェックの頻度を下げたり、なるべく他の事を割り込ませないようにしています。


・その日にやることリストを作る
書いてみるだけでだいぶ頭の中がすっきりします。少し細かく分けて時間も割り振ってみることで、自分のペースがつかみやすくなったり、集中する時間を作りやすくなると思います。


・苦手なことはなるべく早めに
引っかかっていることがあると、そればかり気になって集中できない、ということがあるので、気がかりなことはなるべく早くつぶしておくようにしています。
先にできない場合は、、とりあえずそのことを考えないようにしています。。。


・煮詰まった時はすぱっと休憩する
ちょっとした気付きで、問題が一気に解決する場合があります。
休憩で外に出たりすることで、いったん問題から離れて冷静になると、いろいろな事に気付きやすくなります。


・十分な栄養と睡眠、適度な息抜き
体調が悪かったり、ストレスをためこんでいると仕事以外でもいろんな悪影響が出ます。
忙しい時ほど、生活リズムに気をつけるようにしています。
自分の場合、夜遅くまで仕事していると家に帰ってからもなかなか寝付けないので、夜は遅くなりすぎないようにしています。


・ピンチとチャンスは紙一重
大変な時に少し意識してみると、もっとがんばれる気がしてきます。


今までは一人でプログラミングするようなプロジェクトが多く、今日はそんな中で効率を上げるために意識していたことをまとめてみました。

symfony1.2でtaskから実行されたメソッドかWeb側で実行されたメソッドかを判定する小技

こんちは。松田です。今回は久々にphpネタです。
symfonyで開発をしていると、taskから呼び出された場合と、Web側で実行された際に呼び出された場合とで、実行させる処理を切り分けたい場合がたまーに出てきます。
こんなときに処理を切り分けるための小技を紹介したいと思います。

自分が実際にこの切り分けが必要になったのはこんな状況。

・とある登録ページでレコードを作成
・そのレコードを大量に参照する集計ページが必要
・集計ページを開いた瞬間に集計し計算すると、とーーっても重い
・こまった
・集計結果用テーブルを作り、レコードの登録時にmodelのpostSave()で関連する部分だけ集計しておくことに。
・集計ページは集計済みのテーブルを表示するだけなのでめっちゃ軽い!
・解決ッ!

でもここで問題が発生。
上記の処理の追加後に、symfony:build-all-reload を使用してテストデータを読み込んでみると、膨大なテストレコードがsaveされるたびに集計処理を実行してしまい、テストデータのインポートがいつまでたっても終わらないっ! あわわわわ
ここでtaskからの処理とWebからの処理が必要になったというお話でした。


そしてこの処理を切り分ける方法をいろいろ考えていたのですが、最終的に以下のように実装しています。



<?php
// レコードのモデルクラス内

…

public function postSave($event) 
{
  try {
    
    sfContext::getInstance();
    
  } catch (Exception $e) {

    // 例外がcatchされたらtaskからの処理
    return;
    
  }
  
  // 例外が出なければWebからの処理
  doShuukei();
  
}

…



これに加えて、まとめて集計をおこなうtaskを一つ作成し、テストデータのインポート後に実行することで今度こそ解決。

もっとシンプルに判定する方法が用意されてるのかもしれませんが、調べてもわからなかったのでこんな怪しげな感じになりました。
まあ、ちゃんと動いてるようだし大丈夫だろう。うん。

TextMateで全角スペースと半角スペースの区別ができるようにする

こんにちは。先日、我慢しきれずに、MacBookを購入してしまった橋本です。
開発環境がMacになったということで、最近はTextMateを使って開発をしているのですが、
TextMateを使ってコーディングをしていると、ぱっと見問題なさそうなコードなのにバグが出て、調べてみると全角スペースが隠れていたということがよくあります。
TextMateは元々マルチバイト文字に対応していないため、日本語を無理やりまともな形で表示させると、全角スペースと半角スペースが等幅で表示されてしまい、一見半角なのか全角なのか判断がつきません。
そこで、今回はTextMateで全角スペースと半角スペースを見分けるために、全角スペースをハイライト表示するという設定を紹介します。

設定は以下の手順で行います。
(今回はHTMLファイルで表示させるための設定を例にすすめます。)
1.TextMateのメニューから、「Bundles」の中の「Bundle Editor」の中の「Edit Languages」を選択。

2.左のメニューでHTMLを選択。


3.以下の場所に次のコードを挿入


whitespace-multi = {
	patterns = (
		{	name = 'invalid.whitespace-multi';
			match = '( )';
		},
	);
};




4.以下の場所に次のコードを挿入


{ include = '#whitespace-multi'; },



↓ここに挿入することで、PHPタグ内でもハイライト表示がされるようになります。



5.TextMateのメニューから「Preferences」の「Fonts & Colors」を選択。
6.「+」アイコンをクリックしてElementを追加し、以下のとおり設定する。
Element名: whitespace-multi(ここは他の名前でも大丈夫です)
Scope Selecter: invalid.whitespace-multi(ここはこのとおり入力してください)
背景色(BG): 目立つ色(ここも自由です)



設定は以上です。
上記の設定を行うと、全角スペースが以下のように表示されます。


これで、全角スペースが入っている場合にはハイライト表示されるため、全角スペースの消し忘れに悩まされることもなくなります。

TextMate愛好家の皆様、TextMate2.0が出るまでは上記の方法でなんとか乗り切りましょう!

prettyFormsで、フォーム画面をちょっとおしゃれに。

こんにちは。
新型MacBookのデザインの可愛さに惹かれつつも、いまいち購入に踏み切れないないでいる橋本です。
あと500グラム軽ければ、迷うこと無く購入に踏み切るのですが…。

さて、今日は「prettyForms」というツールを紹介します。
このブログを読んでくださっている方の中には、普段業務システムの開発に携わっておられる方もいらっしゃると思います。
業務システムを作成する際には、以下のようなシンプルなフォーム画面を目にすることも多いのではないでしょうか。



ソース


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>入力フォーム</title> 
</head> 
<body>
  <form id="form-sample" name="form-sample" method="post" action="">
  <p>
    <label for="name">お名前</label>
  </p>
  <p>
    <input type="text"name="name" id="name" >
    <br class="clearAll">
  </p>
  <p>
    <label>性別</label>
  </p>
  <p>
    <input type="radio" name="sex" id="man" value="man" checked="checked">
    <label for="man">男</label>
    <input type="radio" name="sex" id="woman" value="woman">
    <label for="woman">女</label>
    <br class="clearAll">
  </p>
  <p>
    <label for="from">出身地</label>
  </p>
  <p>
    <select name="from" id="from">
      <option>----</option>
      <option value="1">東京</option>
      <option value="2">千葉</option>
      <option value="3">埼玉</option>
      <option value="4">沖縄</option>
    </select>
    <br class="clearAll">
  </p>
  <p>
    <label>趣味</label>
  </p>
  <p>
    <input type="checkbox" name="hobby1" id="walking" value="1" />
    <label for="hobby1">ウォーキング</label>
    <input type="checkbox" name="hobby2" id="cooking" value="2" />
    <label for="hobby2">料理</label>
    <input type="checkbox" name="hobby3" id="programming" value="3" />
    <label for="hobby3">プログラミング</label>
    <br class="clearAll">
  </p> 
  <p>
	<label for="message">コメント記入欄</label>
    <textarea name="message" id="message" rows="4" cols="40">一言コメントをどうぞ</textarea>
    <br class="clearAll">
  </p>
  <p>
    <input type="submit" name="submit" value="登録">
  </p>
  </form>
</body>
</html>


このようなシンプルなフォーム画面、
機能的には問題ないのですが、シンプルすぎてなんだか見た目がちょっと寂しいとは思いませんか。
ただ、そう思ったとしても、実際業務を行う中でこのようなシンプルなフォーム画面のデザインに、多くの時間を費やすことは中々難しいのではないかと思います。

今回紹介するツールは、そういったお悩みを解決するツールです。

使い方は非常に簡単。
1.まずは「prettyForms」を以下のサイトからDLし、中身をフォームのhtmlと同じフォルダに展開します。
Agave Group >> Blog Archive >> (Functional) Pretty Forms

2.フォームのhtmlに以下の記述を加えます。

ヘッダ


<head>
 <script type="text/javascript" src="prettyForms.js"></script>
 <link rel="stylesheet" href="prettyForms.css" type="text/css" />
</head>

ボディ


<body onload="prettyForms()">
</body>



3.改めてフォームを表示します。


先ほどのシンプルなフォームがちょっとおしゃれなフォームに変わりましたね。

いやー、すばらしい!!

…と、手放しに喜びたいところなのですが、
このツールを使用するには、いくつか注意点があります。

もう皆さんお気づきかと思いますが、ソースコード中にlabel要素が多用してあります。
実は、このツールはlabel要素を基準としてレイアウトを行います。
そのため、表示する全ての要素に対してlabel要素を追加する必要があります。

また、ソースコード中に<br class="clearAll" />というタグが多数あるのですが、この「clearAll」というクラス名は元々定義されているクラス名で、自動で行われるレイアウト(labelの右側にフォーム部品が回り込むようなレイアウト)を解除するために使用します。
回り込みのレイアウトを解除するためには、いちいちこのタグを挿入する必要があり、この点が少し面倒です。

label要素の記述が必須だったり、clearAllクラスを使って回り込みレイアウトを解除したりしなければいけなかったりと、使用するには不便なことも多いのですが、デザインに時間をかけられない案件などで手軽に見栄えのするフォームを作りたい際には重宝するのではないかと思います。

是非一度使ってみてはいかがでしょうか。

ちょっと使えるMySQLの小技5つ+1

こんにちは。最近ガスを止められ温もりの無い生活を送っている松田です。

今回は最近自分が知ったMySQLの小技をいくつか書いてみます。
んなもん常識だろ!ってネタがあっても優しく見守ってあげてください。

まず今回の実行サンプルには以下のテーブルを使ってます。


mysql> SELECT * FROM user_m;
+---------+----------+---------------------+
| user_id | name     | create_datetime     |
+---------+----------+---------------------+
|       1 | atsushi  | 2007-05-17 21:53:40 | 
|       2 | joe      | 2007-05-17 21:53:59 | 
|       3 | masahiro | 2007-05-18 21:54:02 | 
|       4 | saito    | 2007-05-18 21:54:05 | 
|       5 | yuka     | 2007-05-18 21:54:10 | 
+---------+----------+---------------------+



1. 実行結果をファイルに書き出す / INTO OUTFILE|DUMPFILE
SELECTした結果を直接ファイルに出力する方法です。SELECT文の後ろに INTO OUTFILEとファイル名を指定することで実行できます。



 SELECT * FROM user_m INTO OUTFILE "/tmp/output.txt" ;


出力されるテキストは以下のようになります。
/tmp/output.txt


 1 atsushi 2007-05-17 21:53:40
 2 joe 2007-05-17 21:53:59
 3 masahiro  2007-05-18 21:54:02
 4 saito 2007-05-18 21:54:05
 5 yuka  2007-05-18 21:54:10


通常は半角スペース区切りで出力されますが、ファイル名の後ろに FIELDS TERMINATED BY ',' を付けるとカンマ区切りにすることができます。これを使えばCSVファイルも楽に作れそうです。

INTO DUMPFILE は出力するレコードが一つだけの時のみ使用できます。
これは画像などのデータを入れているBLOB型のレコードから画像ファイルを作成する場合などに使えます。



2. GROUP BY のついでにソートしたい / GROUP BY 条件 ASC|DESC
GROUP BY でグループ化し、その結果でソートするには通常以下のようなSQLを書きます。



SELECT DATE(create_datetime), COUNT(*) FROM user_m GROUP BY DATE(create_datetime) ORDER BY DATE(create_datetime) DESC;


これをもっと簡単に書く方法が存在します。
ORDER BYを省略し、GROUP BYの後ろにASCかDESCを付けちゃうのです。
これだけでGROUP BYの値をソートに使用することができます。



SELECT DATE(create_datetime), COUNT(*) FROM user_m GROUP BY DATE(create_datetime) DESC;


GROUP BY に指定する条件が複雑なSQLの場合は地味に便利です。



3. GROUP BY した結果の合計出したいんだけど・・・ / GROUP BY 条件 WITH ROLLUP
まずは日付ごとに登録された人数を出してみます。


mysql> SELECT DATE(create_datetime), COUNT(*) FROM user_m GROUP BY DATE(create_datetime);
+-----------------------+----------+
| DATE(create_datetime) | COUNT(*) |
+-----------------------+----------+
| 2007-05-17            |        2 | 
| 2007-05-18            |        3 | 
+-----------------------+----------+

5月17日に作られたユーザーが2人、5月18日に作られたユーザーが3人います。
こういったGROUP BYを使った出力結果の合計を出すことができるのが WITH ROLLUP です。


mysql> SELECT DATE(create_datetime), COUNT(*) FROM user_m GROUP BY DATE(create_datetime) WITH ROLLUP;
+-----------------------+----------+
| DATE(create_datetime) | COUNT(*) |
+-----------------------+----------+
| 2007-05-17            |        2 | 
| 2007-05-18            |        3 | 
| NULL                  |        5 | 
+-----------------------+----------+

これで合計数「5」が得られました。合計数と無関係なカラムにはNULLが入ります。
ただしこの検索SQLにLIMITを付ける場合、合計前の表にLIMITがかけられるわけではなく、合計後の上記のような表にLIMITがかけられるだけなので注意しましょう。



4. 複数行の結果を一行で出したい / GROUP_CONCAT
複数の要素を一行にまとめて返します。
要するにPHPの join や implode と同じ機能ですね。


mysql> SELECT GROUP_CONCAT(name SEPARATOR '/') FROM user_m;
+----------------------------------+
| GROUP_CONCAT(name SEPARATOR '/') |
+----------------------------------+
| atsushi/joe/masahiro/saito/yuka/ | 
+----------------------------------+

SEPARATORを省略すると、自動的にカンマ「,」で区切られるようです。



5. DELETEしてからINSERTするのメンドクサイよね / REPLACE
テーブルに値をINSERTするとき、特定のフィールドに同じ値を入れたくないことが良くあります。そんなときはフィールドにUNIQUE属性を付け、さらにDELETEを一度発行してからINSERTしたりします(よね?)。
このDELETEとINSERTをまとめてやってくれるのが REPLACE です。
REPLACE はPRIMARY KEYやUNIQUE属性が付いているフィールドに同じ値を入力しようとすると、自動的にDELETE、INSERTを行ってくれます。

ここでは name にUNIQUE属性を付けて試してみました。



mysql> SELECT * FROM user_m;
+---------+----------+---------------------+
| user_id | name     | create_datetime     |
+---------+----------+---------------------+
|       1 | atsushi  | 2007-05-17 21:53:40 | 
|       2 | joe      | 2007-05-17 21:53:59 | 
|       3 | masahiro | 2007-05-18 21:54:02 | 
|       4 | saito    | 2007-05-18 21:54:05 | 
|       5 | yuka     | 2007-05-18 21:54:10 | 
+---------+----------+---------------------+
5 rows in set (0.00 sec)
 
mysql> REPLACE INTO user_m (name, create_datetime) VALUES ('atsushi', NOW());
Query OK, 2 rows affected (0.03 sec)
 
mysql> SELECT * FROM user_m;
+---------+----------+---------------------+
| user_id | name     | create_datetime     |
+---------+----------+---------------------+
|       6 | atsushi  | 2007-05-18 22:10:11 | 
|       2 | joe      | 2007-05-17 21:53:59 | 
|       3 | masahiro | 2007-05-18 21:54:02 | 
|       4 | saito    | 2007-05-18 21:54:05 | 
|       5 | yuka     | 2007-05-18 21:54:10 | 
+---------+----------+---------------------+
5 rows in set (0.00 sec)


user_id=1の'atsushi'が削除され、新たにuser_id=7の'atsushi'がINSERTされました。
REPLACEを行った直後、「2 rows affected」になっているのは、DELETEとINSERTの2レコードに対して操作を行ったからのようです。

でも'atsushi'の表示位置が元の位置と同じなのはなぜなんだろう。
通常のINSERTとは違う処理ということでしょうか。



6. 複数のテーブルにまとめてINSERTしたい!
そんな方法があるようです。マルチテーブル・インサートと呼ぶらしいです。

サンプルを作ろうかと思ったのですが参考先ページ以上の例が出せそうにないのでリンクのみで。
http://www.atmarkit.co.jp/fdb/rensai/sqlclinic12/sqlclinic12_1.html

うーん、こりゃすごい。全然知らなかった。
すごい!とは思うものの使う場面が思い浮かびません。。


まだまだ奥が深いMySQL・・・
もっと勉強が必要なことを思い知らされました。