2.7 主キーの生成
主キーとして使うデータは、顧客名や商品名など、アプリケーションロジックとして決まる場合もあるが、データベース上で一意の値を自動生成したい場合もあるだろう。排他制御の点から、アプリケーション側で一意の値を作るのは面倒であるが、SQL Anywhereの機能を使えば簡単だ。SQL Anywhereには、(1) 連番を生成するAUTOINCREMENT機能、(2) 一意の値を生成するUUID(Universally Unique Identifier)機能がある。
2.7.1 AUTOINCREMENT
カラムのデフォルト値としてAUTOINCREMENTを指定すると、正整数の連番が自動的に生成される。カラムに値を明示して行を追加すればその値が使用され、そうでなければ、一意の値が自動生成される。生成される値は、そのカラムで使用されている最大の正整数(なければゼロ)に1を足した値となる。なお、数字の並びに空きがあったとしても、それが考慮されることはない。
CREATE TABLE customer ( cust_id INTEGER NOT NULL DEFAULT AUTOINCREMENT, cust_name VARCHAR(256), PRIMARY KEY ( cust_id ) ); INSERT INTO customer (cust_name) VALUES ('first'); ← 自動生成 INSERT INTO customer (cust_id, cust_name) VALUES (10, 'second'); ← 明示 INSERT INTO customer (cust_name) VALUES ('third'); ← 自動生成 commit; SELECT * FROM customer;
1,'first' 10,'second' 11,'third' ← 空きは考慮されない
自動生成された値の取得
使用中のコネクション内で直近に自動生成された値は、グローバル変数の@@identityで取得できる。
SELECT @@identity;
11
自動生成される値のリセット
次回に自動生成される値を、sa_reset_identityプロシージャで設定できる。ここで設定された値に1を足したものが次に自動生成される。ただし、重複する値を避けて自動生成されることはないので、重複した場合は追加時にエラーとなる。
なお、TRUNCATE TABLE文で全行削除した場合は、ゼロにリセットされて、次回は1が生成される。
DELETE customer WHERE cust_id >= 10; CALL sa_reset_identity('customer', 'dba', 1); ← 1にリセット INSERT INTO customer (cust_name) VALUES ('forth'); ← 自動生成 commit; SELECT * FROM customer;
1,'first' 2,'forth'
2.7.2 UUID
UUID(Universally Unique Identifier)はGUID(Globally Unique Identifier)とも呼ばれ、実行プロセスやマシンによらない一意の値(16バイト)を生成する機能である。そのため、Mobile Link同期環境など、データベースが分散するときの主キーとして便利だ。
SQL Anywhereでは、NEWID
関数でUUIDを生成でき、その値を文字列と相互変換する関数(UUIDTOSTRやSTRTOUUID)も用意されている。
CREATE TABLE orders ( order_id UNIQUEIDENTIFIER NOT NULL DEFAULT newid(), order_date DATE, PRIMARY KEY (order_id) ); INSERT INTO orders (order_date) VALUES ('2005-1-1'); commit; SELECT UUIDTOSTR(order_id), order_date FROM orders;
'36a18c0a-d17d-4f79-b5cc-04432b25c1c8','2005-01-01'
2.8 スケジュールとイベント
SQL Anywhereには、スケジュールとイベントと呼ばれる機能があり、指定されたタイミングで特定の処理を実行させることができる。スケジュール機能は、OSの時刻をもとに実行される。一方、イベント機能は、ユーザーからの接続があったなどのシステムイベントをもとに実行される。なお、SQL Anywhere内部では、スケジュールもイベントの一種とみなされているので、混乱のない限り、スケジュールにも「イベント」という語を使用して説明する。
スケジュールは、定まった時刻や間隔で処理を実行できるので、データベースのバックアップやインデックスの再構築などデータベースのメンテナンス処理に都合が良い。一方、イベントは、ユーザーからの接続を調べたり、ディスクの空き容量を調べたりできるので、管理者へ警告メールを送信するなどといったデータベースの監視に適している。
2.8.1 スケジュール
処理が実行される時刻を時間や曜日で指定できる。毎週月曜日であるとか、3時間ごとといった指定も可能だ。例えば、毎日深夜1時にバックアップを実行するには、次のようにイベントを作成する。
CREATE EVENT IncrementalBackup SCHEDULE START TIME '1:00 AM' EVERY 24 HOURS HANDLER BEGIN BACKUP DATABASE DIRECTORY 'c:エエbackup' TRANSACTION LOG ONLY TRANSACTION LOG RENAME MATCH END
CREATE EVENT文でイベント名を定義し、SCHEDULE部で時刻などを指定する。続くHANDLER部以下に処理のスクリプトを書く。処理は、SQLスクリプトとして書ければ、どのような処理であってもよい(ここでは、スクリプトの詳細を割愛する)。
SCHEDULE部では、上記の例以外にも、次のような時刻指定が可能だ。
BETWEEN '8:00AM' AND '6:00PM' EVERY 1 HOURS ON ('Monday','Tuesday','Wednesday','Thursday','Friday')
これは、平日の朝8時から夕方6時まで1時間ごとに実行することを意味している。
スケジュールでは次の点に注意する。
- スケジュールで指定された時刻にデータベースが動いていないと実行されない。
- 前の処理が終了してから次の処理が予約される。例えば、処理に70分かかるスケジュールを1時間おきに実行されるように指定しても、実際には2時間おきに実行される。
2.8.2 イベント
イベントは、SQL Anywhereのシステムイベントがトリガとなって実行される。次の例では、トランザクションログファイルが10MBを超えると、バックアップを実行し、トランザクションログファイルを切り替える。
CREATE EVENT LogLimit TYPE GrowLog WHERE event_condition( 'LogSize' ) > 10 HANDLER BEGIN BACKUP database DIRECTORY 'c:エエlogs' TRANSACTION LOG ONLY TRANSACTION LOG RENAME MATCH END
スケジュールと同様に、CREATE EVENT文でイベントを定義し、HANDLER部に処理を記述する。
スケジュールと異なる点は、SCHEDULE部で時刻を指定するのではなく、TYPEでイベント種別を指定し、必要ならWHEREで条件を指定する点だ。上記の例では、トランザクションログファイルのサイズが増加したことを意味する「GrowLog」イベントが起こったとき、ファイルサイズが10MBを超えたなら、処理が実行されることを意味している。
イベント種別には以下のものが用意されている。
イベント種別 | 説明 |
BackupEnd | バックアップ実行後 |
DatabaseStart | データベース起動後 |
Connect | ユーザーからの接続時 |
ConnectFailed | 接続失敗時 |
Disconnect | ユーザーの接続が切断されたとき |
DBDiskSpace | DBファイルがあるディスクの空き容量をポーリング 指定可能条件:DBFreePercent、DBFreeSpace |
LogDiskSpac | トランザクションログファイルがあるディスクの空き容量をポーリング 指定可能条件:LogFreePercent、LogFreeSpace |
TempDiskSpace | テンポラリファイルがあるディスクの空き容量をポーリング 指定可能条件:TempFreePercent、TempFreeSpace |
GrowDB | データベースファイルのサイズが増えたとき 指定可能条件:DBSize |
GrowLog | トランザクションログファイルのサイズが増えたとき 指定可能条件:LogSize |
GrowTemp | テンポラリファイルのサイズが増えたとき 指定可能条件:TempSize |
GlobalAutoIncrement | Global Auto Incrementの数が消費されたとき 指定可能条件:RemainingValues |
RAISERROR | SQLエラーが起こったとき 指定可能条件:ErrorNumber |
ServerIdle | データベースサーバのアイドル状態をポーリング 指定可能条件:IdleTime |
なお、すべてのイベント種別に対して、前回実行時からの間隔を指定する条件であるIntervalを指定できる。