[AIR] SQLiteを使ってDBに挑戦してみる

2010/04/8

こんにちは。きんくまです。
今回はAIRを使ってDBに挑戦してみようと思います。
私のDBスペックは、DBは業務で全く使ったことがなく、ちょびっと知識をかじったぐらい。

↓今回つくるやつ。テキスト入力欄にSQL文を書いてSQL実行ボタンを押すと一覧が表示されます。

sqlquery1

今回の参考書です。
>> 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でも使用できます)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?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)データベースに接続する

の部分は、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

sqlquery3

4)テーブルにデータを挿入・更新・検索する

テーブルができたんで、データをいれてみましょう。

INSERT INTO test1 VALUES(null, '佐藤', '0123-45-6789');

とやってSQL実行ボタンをおして、エラーがでなければ成功

データを確認します。

SELECT * FROM test1;

とやって、一覧がでてきたらOKです。

注意点

AIRのSQLは他のSQLとは違う部分があるので、SQL文がうまく通らないなあと
思ったときは、下の仕様書のページで確認してみたほうがよさそうです。

>> ローカルデータベースでの SQL サポート

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

LINEスタンプ作りました!
毎日使える。とぼけたウサギ。LINEスタンプ販売中! 毎日使える。とぼけたウサギ

ページトップへ戻る