こんにちは。きんくまです。
今回はAIRを使ってDBに挑戦してみようと思います。
私のDBスペックは、DBは業務で全く使ったことがなく、ちょびっと知識をかじったぐらい。
↓今回つくるやつ。テキスト入力欄にSQL文を書いてSQL実行ボタンを押すと一覧が表示されます。

今回の参考書です。
>> SQLの書き方のツボとコツがゼッタイにわかるドリル本―最初からそう教えてくれればいいのに!
>> Adobe AIR クックブック ―プロフェッショナルに学ぶRIAプログラミングの実践
データベースって何?
・簡単にいうと、表組みデータ(エクセルみたいの)。
・それを検索しやすくしたもの。
だと理解。
AIRには、データベースのSQLiteを使うことができるので、それを使って学習してみようと
思いました。
データベースを使う方法
1)データベースを作る(SQLiteの場合は1つのファイル)
2)データベースに接続する
3)テーブルを作る(1つのデータベースにいくつでも作れる)
4)テーブルにデータを挿入・更新・検索する
となります。それで、これをためせるプログラムを作りました。
AIR本を参考にいろいろと書き加えました。
Flex4が出てネット上でもニュースになってるので、
家にあったもののほとんど使ってなかったFlex3を使ってみました。
なんでmxmlです。
table情報を取得する方法がAIR本に載ってなかったので、ASDocから調べたらなんかできました。
loadSchema()やってから、getSchemaResult()やるみたい。
普通のSQLだとtable情報を調べるのもSQL文を書くんだけど、AIRはちょっとばかし
勝手が違うみたい。
■データベースのユーティリティクラス(ArrayCollectionをArrayに変更すれば普通のflaでも使用できます)
package
{
import flash.data.SQLConnection;
import flash.data.SQLResult;
import flash.data.SQLSchemaResult;
import flash.data.SQLStatement;
import flash.data.SQLTableSchema;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
import flash.filesystem.File;
import mx.collections.ArrayCollection;
public class DBUtil extends EventDispatcher
{
private var _myDB:File;
private var _isOpen:Boolean = false;
private var _dbConn:SQLConnection;
private var _resultArrayCollection:ArrayCollection;
public static const ASYNC_CONNECT_COMPLETE:String = "async_connect_complete";
public static const ASYNC_SQL_COMPLETE:String = "async_sql_complete";
public static const SCHEMA_COMPLETE:String = "schema_complete";
public function get myDB():File
{
return _myDB;
}
public function get isOpen():Boolean
{
return _isOpen;
}
public function get resultArrayCollection():ArrayCollection
{
return _resultArrayCollection;
}
public function DBUtil()
{
createLocalDB();
}
public function createLocalDB():void
{
var folder:File = File.applicationStorageDirectory.resolvePath('db');
folder.createDirectory();
_myDB = folder.resolvePath('myDBFile.db');
openLocalDB(_myDB, true);
}
public function openLocalDB(dbFile:File, isAsync:Boolean):void
{
_dbConn = new SQLConnection();
if(isAsync){
_dbConn.openAsync(dbFile);
_dbConn.addEventListener(SQLEvent.OPEN, sqlOpenHD);
_dbConn.addEventListener(SQLErrorEvent.ERROR, sqlOpenErrorHD);
}else{
try{
_dbConn.open(dbFile);
}catch(e:SQLErrorEvent){
trace('SQL Error: ' + e.error.message);
trace('SQL Error Detail: ' + e.error.details);
}
}
}
public function sqlOpenHD(e:SQLEvent):void
{
_isOpen = true;
dispatchEvent(new Event(ASYNC_CONNECT_COMPLETE));
}
public function sqlOpenErrorHD(e:SQLErrorEvent):void
{
_dbConn.removeEventListener(SQLEvent.OPEN, sqlOpenHD);
_dbConn.removeEventListener(SQLErrorEvent.ERROR, sqlOpenErrorHD);
//trace('SQL Error: ' + e.error.message);
//trace('SQL Error Detail: ' + e.error.details);
dispatchEvent(e);
}
public function sqlExcuteErrorHD(e:SQLErrorEvent):void
{
var state:SQLStatement = e.target as SQLStatement;
state.removeEventListener(SQLEvent.RESULT, sqlStatementResultHD);
state.removeEventListener(SQLErrorEvent.ERROR, sqlExcuteErrorHD);
//trace('SQL Error: ' + e.error.message);
//trace('SQL Error Detail: ' + e.error.details);
dispatchEvent(e);
}
public function executeSQLState(sqlText:String):void
{
if(isOpen == false){
throw new Error('DB is not connected.');
return;
}
var state:SQLStatement = new SQLStatement();
state.sqlConnection = _dbConn;
state.text = sqlText;
state.addEventListener(SQLEvent.RESULT, sqlStatementResultHD);
state.addEventListener(SQLErrorEvent.ERROR, sqlExcuteErrorHD);
state.execute();
}
private function sqlStatementResultHD(e:SQLEvent):void
{
var state:SQLStatement = e.target as SQLStatement;
state.removeEventListener(SQLEvent.RESULT, sqlStatementResultHD);
state.removeEventListener(SQLErrorEvent.ERROR, sqlExcuteErrorHD);
var result:SQLResult = state.getResult();
var temp:Array = result.data is Array ? result.data : [{rows:result.rowsAffected}];
_resultArrayCollection = new ArrayCollection(temp);
dispatchEvent(new Event(ASYNC_SQL_COMPLETE));
}
public function getTableInfo():void
{
_dbConn.addEventListener(SQLEvent.SCHEMA, sqlSchemaCompHD);
_dbConn.addEventListener(SQLErrorEvent.ERROR, sqlSchemaErrorHD);
_dbConn.loadSchema();
}
private function sqlSchemaCompHD(e:SQLEvent):void
{
_dbConn.removeEventListener(SQLEvent.SCHEMA, sqlSchemaCompHD);
_dbConn.removeEventListener(SQLErrorEvent.ERROR, sqlSchemaErrorHD);
var result:SQLSchemaResult = _dbConn.getSchemaResult();
var tables:Array = result.tables;
var temp:Array = [];
for each(var tableSchema:SQLTableSchema in tables){
temp.push({
database:tableSchema.database,
name:tableSchema.name,
sql:tableSchema.sql,
columns:tableSchema.columns.length
});
}
_resultArrayCollection = new ArrayCollection(temp);
dispatchEvent(new Event(SCHEMA_COMPLETE));
}
private function sqlSchemaErrorHD(e:SQLErrorEvent):void
{
_dbConn.removeEventListener(SQLEvent.SCHEMA, sqlSchemaCompHD);
_dbConn.removeEventListener(SQLErrorEvent.ERROR, sqlSchemaErrorHD);
//trace('SQL Error: ' + e.error.message);
//trace('SQL Error Detail: ' + e.error.details);
dispatchEvent(e);
}
}
}
■そして、これを使う用のMXML
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="620" height="420">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.collections.ArrayCollection;
private var _dbUtil:DBUtil;
[Bindable]
private var _myResultAC:ArrayCollection;
private function init():void
{
excuteBtn.addEventListener(MouseEvent.CLICK, excuteSQLBtnClickHD);
tableInfoBtn.addEventListener(MouseEvent.CLICK, tableInfoBtnClickHD);
_dbUtil = new DBUtil();
_dbUtil.addEventListener(DBUtil.ASYNC_CONNECT_COMPLETE, dbAsyncCompHD);
}
private function tableInfoBtnClickHD(e:MouseEvent):void
{
_dbUtil.addEventListener(DBUtil.SCHEMA_COMPLETE, dbSchemaCompHD);
_dbUtil.addEventListener(SQLErrorEvent.ERROR, dbSchemaErrorHD);
_dbUtil.getTableInfo();
}
private function dbSchemaErrorHD(e:SQLErrorEvent):void
{
_dbUtil.removeEventListener(DBUtil.SCHEMA_COMPLETE, dbSchemaCompHD);
_dbUtil.removeEventListener(SQLErrorEvent.ERROR, dbSchemaErrorHD);
Alert.show(e.error.message + '\n' + e.error.details);
}
private function dbSchemaCompHD(e:Event):void
{
_dbUtil.removeEventListener(DBUtil.SCHEMA_COMPLETE, dbSchemaCompHD);
_dbUtil.removeEventListener(SQLErrorEvent.ERROR, dbSchemaErrorHD);
_myResultAC = _dbUtil.resultArrayCollection;
//Alert.show('table schema read complete');
}
private function excuteSQLBtnClickHD(e:MouseEvent):void
{
_dbUtil.addEventListener(DBUtil.ASYNC_SQL_COMPLETE, dbSQLCompleteHD);
_dbUtil.addEventListener(SQLErrorEvent.ERROR, dbSQLErrorHD);
_dbUtil.executeSQLState(sqlInputTxt.text);
}
private function dbSQLErrorHD(e:SQLErrorEvent):void
{
_dbUtil.removeEventListener(DBUtil.ASYNC_SQL_COMPLETE, dbSQLCompleteHD);
_dbUtil.removeEventListener(SQLErrorEvent.ERROR, dbSQLErrorHD);
Alert.show(e.error.message + '\n' + e.error.details);
}
private function dbSQLCompleteHD(e:Event):void
{
_dbUtil.removeEventListener(DBUtil.ASYNC_SQL_COMPLETE, dbSQLCompleteHD);
_dbUtil.removeEventListener(SQLErrorEvent.ERROR, dbSQLErrorHD);
_myResultAC = _dbUtil.resultArrayCollection;
//Alert.show('SQL excuted !');
}
private function dbAsyncCompHD(e:Event):void
{
Alert.show("SQL connection complete !");
}
]]>
</mx:Script>
<mx:Panel x="0" y="0" width="588" height="388" layout="absolute" title="SQLTest" initialize="init();">
<mx:DataGrid x="10" y="111" width="548" height="227" id="myDG" dataProvider="{_myResultAC}"/>
<mx:Button x="10" y="81" label="SQL実行" id="excuteBtn"/>
<mx:Button x="88" y="81" label="table情報" id="tableInfoBtn"/>
<mx:TextArea x="10" y="10" width="548" height="63" id="sqlInputTxt" wordWrap="true" editable="true"/>
</mx:Panel>
</mx:WindowedApplication>
解説
1)データベースを作る(SQLiteの場合は1つのファイル)
2)データベースに接続する
の部分は、
public function createLocalDB():void
{
var folder:File = File.applicationStorageDirectory.resolvePath('db');
folder.createDirectory();
_myDB = folder.resolvePath('myDBFile.db');
openLocalDB(_myDB, true);
}
public function openLocalDB(dbFile:File, isAsync:Boolean):void
{
_dbConn = new SQLConnection();
if(isAsync){
_dbConn.openAsync(dbFile);
_dbConn.addEventListener(SQLEvent.OPEN, sqlOpenHD);
_dbConn.addEventListener(SQLErrorEvent.ERROR, sqlOpenErrorHD);
}else{
try{
_dbConn.open(dbFile);
}catch(e:SQLErrorEvent){
trace('SQL Error: ' + e.error.message);
trace('SQL Error Detail: ' + e.error.details);
}
}
}
で、1つのDB用のファイル(myDBFile.db)を作って、同期か非同期で開くという感じです。
mxmlの方は起動したら、すでにここまでやってある状態にしました。
3)テーブルを作る(1つのデータベースにいくつでも作れる)
はテキスト入力欄に
CREATE TALBE test1( id INTEGER PRIMARY KEY, name TEXT, phone TEXT );
とか入力して、SQL実行ボタンを押せばテーブルが作成されます。
それで、ここでもAIR仕様があって、AIRのSQLiteでは使用可能な型がちょびっと変わってるみたいです。
>> ローカルデータベースでの SQL サポート – Adobe® Flex™ 3.2 リファレンスガイド データ型のサポート
SQL本によれば、INT型とかVARCHAR型とかいうのがあるみたいなんですけど、
AIRのSQLiteだとINTEGER型、TEXT型というふうになっとります。
tableをうまく作成したら、table情報ボタンをおします。そしたら、↓の画面のようになったらOK

4)テーブルにデータを挿入・更新・検索する
テーブルができたんで、データをいれてみましょう。
INSERT INTO test1 VALUES(null, '佐藤', '0123-45-6789');
とやってSQL実行ボタンをおして、エラーがでなければ成功
データを確認します。
SELECT * FROM test1;
とやって、一覧がでてきたらOKです。
注意点
AIRのSQLは他のSQLとは違う部分があるので、SQL文がうまく通らないなあと
思ったときは、下の仕様書のページで確認してみたほうがよさそうです。