カテゴリー: Development

PostgreSQL覚書 Triggerあれこれ

10年前にOracleで作成して以来、久しぶりにトリガーを作成してみた。
しかも、PostgreSQLで。

いろいろできなかったことがあったので調べてみたが、結局わからないところは代替案(要するに適当)で作った。
トリガー作成なんて、今後もあまりやらないだろうから、覚書は細かく書いておくことに。

まず、Functionを作ってからTriggerを作成。

--------------------------------------------------------
-- 走らせる処理はこっちに書く(言語はplpgsql)
--------------------------------------------------------
CREATE OR REPLACE FUNCTION SET_XX_FUNC()
  RETURNS trigger AS $$
    DECLARE
        -- 変数定義 --
    BEGIN
        -- 処理 --
    END;
$$ LANGUAGE ’plpgsql’;

--------------------------------------------------------
-- {table}に設定したテーブルに行が挿入、または行更新された後に処理を走らせる
--------------------------------------------------------
CREATE OR REPLACE TRIGGER SET_XX
 AFTER INSERT OR UPDATE ON {table} FOR EACH ROW
 EXECUTE PROCEDURE SET_XX_FUNC();

さて、ここまでは良い。
こっからだ。

--------------------------------------------------------
--★ 変数の設定
--------------------------------------------------------
DECLARE item_a int;
DECLARE item_b int :=999 ;
item_a := 1;

>>1つ目は変数のみ定義。
>>2つ目は変数定義と同時に初期値を設定する方法。
>>3つ目は定義した変数に値を入れる方法。

--------------------------------------------------------
--★ 情報の取得方法その1(普通のSELECT文)
--------------------------------------------------------
DECLARE item_a int;
DECLARE item_b int;
DECLARE item_c int;
-- (中略) --
SELECT a,b,c INTO item_a,item_b,item_c 
FROM {table} WHERE key1=NEW.key1 ;

>>SELECT文で取得したデータを変数に入れる場合の書き方はこんな感じ。
  SELECT a INTO item_a, b INTO item_b … ってな書き方はNG。
>>トリガーで更新・挿入したデータの情報を取得する場合は、NEW.{カラム名}で。

--------------------------------------------------------
--★ 情報の取得方法その2(Executeを利用したSELECT文)
--------------------------------------------------------
DECLARE add_months text = ’2months’;
DECLARE next_kigen text = ’’;
-- (中略) --
EXECUTE ’SELECT TO_CHAR(
           DATE_TRUNC(’’month’’
                , CURRENT_TIMESTAMP 
	               || ’ + interval ’ || quote_literal(add_months) || ’)’ 
	               || ’ + interval ’’-1days’’,’’YYYYMMDD’’)’
 INTO next_kigen; 

>>普通のSELECT文ではどうしても無理なものは、文字列のSELECT文を実行することになる。
  上の例は、現在日時から翌月末の日付(+2ヶ月-1日)を取得する方法。
  add_monthsがころころ変わる場合(3か月後、4か月後と)、普通のSELECT文ではどうしてもできなかった。
  あとは、サブクエリ―を使う場合もSELECT文では書けないと思っておいたほうがよい。
  (テーブル別名=エイリアスが使えないので。)
  なので、文字列を生成して
       EXECUTE 文字列 INTO 変数名;
  で検索結果をINTOの後ろの変数に格納させる。
  文字列内のシングルクォーテーションは’’と、2連続にすること。
>>quote_literal関数はよくわからないが、変数の型にあったquateを設定すると思う。
  文字列の間で変数を使いたいときは、必ずこの関数を使う。(使わんかったら動かんかったし)
  ちなみに、DATE_TRUNC(‘month’,{date_type})は月初を求めるときの関数。

--------------------------------------------------------
--★ 更新後の{item1}が0以下なら処理をやめる(条件文の例)
--------------------------------------------------------
IF NEW.{item1} <= 0 THEN
  RETURN NEW;
END IF;

>>途中で処理を抜ける処理の書き方がイマイチわからなかったので、とりあえずRETURN NEWしてる。
  (正しい方法を教えて!!)

--------------------------------------------------------
--★ 検索結果がないときの判定
--------------------------------------------------------
IF NOT FOUND THEN
  RETURN NEW;
END IF;

>>なのだが、これってカーソル処理やFOR文でしか作動しないように思う。

——————————————————–
–★ OLDとNEW
——————————————————–
OLDは更新前のレコードで、NEWは更新後のレコード。
NEW.{カラム名} という感じで使う。
なので、DELETEのトリガーの場合はOLDしかないし、INSERTの場合はNEWしかない。
今回は、AFTER INSERT OR UPDATE ~つまり更新・挿入後に行う~の処理なので、NEWしか使っていない。

衰えた脳みそをフル活用させて1日がかりで作ったのだが、うまく動かなかった ・・・・

で、デバッグ。
本当はログ出力して経過をみたかったのだけれど、ログ出力の仕方がよくわからないし、テスト環境と本番環境で異なる設定をしてもなぁ・・・と思って、動作途中で強制エラーを発生させることにした。

--------------------------------------------------------
--★ RAISE EXCEPTION(強制的に例外を発生させる)
--------------------------------------------------------
DECLARE add_months text = ’2months’;
-- (中略) 
RAISE EXCEPTION '% ここまで終わったぜ', add_months;

>>エラーメッセージに「2months ここまで終わったぜ」と表示される。
  (%は可変値で、2つ目以降の引数で設定する。Cとかの%dとかと同じ)
  なので、とりあえず、ここまでは走ってるよなぁ・・・ということで、
  次はこの例外発生処理を後ろに移動させてから実行する。
  これを何度か繰り返して、なんとか思い通りに動作するところまで行った。

とりあえず、直近で必要な情報はこんなところ。
今回はカーソルとかは使わなかったので、使うときはまた追記なり投稿なりしようと思う。
EXECUTEとかの使い方が難しいし、面倒だった。

まぁ、こんだけ書いておけば、次回はさほどオロオロすることもないだろう。

PostgreSQL覚書 日付8ケタ数値に変換

SQLServerとPostgreSQLを行ったり来たりしてると、どうもこんがらがって困る。

<現在日付を8桁にする>
to_char(current_timestamp,’YYYYMMDD’)::numeric

SQLServerだとCONVERTを使うんで、CONVERT・・・・と書きそうになった。

Xcode覚書 Core Data/マイグレーション

XcodeでMaster-Detailのテンプレートを使って、お勉強をしていたのだが、Detailに表示するデータを増やしたくて、xcdatamodeldを開いて、Attributionを増やした。

って、それだけで動かなくなった・・・

調べたら「マイグレーション」をしなければならない!ってなってて、「マイグレーション」ってなんやねん?ってなった。

よくわからないが、

・古いデータが最新のデータ構造と違うから動かへんねん
・せやから、古いデータ消しなはれ
・でもな、マイグレーションいうのがあって、項目の増減をどないかしてくれるらしいわ
・自動でマイグレーションを行わせたいんやったら、コーディネータ構築のoptionを変えとき!

まぁ、大阪弁で言うならこんな感じか・・・
(はしょりすぎだけど)

で、ソースは、

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

と、変数を設定しておいて、

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:url
options:options
error:&err]);

デフォルトでnillになっているoptionsパラメータ?を設定した変数に変更する。

(自分への覚書)
Entityを追加したり、Attributeを増減させたりした後、
Core DataのNSManagedObject Subclassファイルを新しく作成するのを忘れずに。

Xcode覚書 main.mでエラー確認

Buildが成功しても、なぜかエラーになるので、エラー原因を突き止めるための方法。

困ったことに、また忘れてしまい、過去に作ったコードを探しまくり、ようやく見つけた。

 @autoreleasepool {
  @try {
   return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  } @catch (NSException *exception) {
   NSLog(@"%@",exception);
  }
 }

TryーCatchでエラーをログに表示させれば、ちょっとは原因に近づけるはず。(ハズ)

ExcelVBA覚書 ロック関連と数式セル判断

なんだかんだで、Zoo Keeper対戦中。
文句言ってても、結局すきなんだろぉ~・・・えぇ好きです(ポッ)、と下らん一人芝居をしたところで、メモ。

‘———————————————————

まずは、Excelマクロのロックあれこれ。

Const LOCK_PW as String = "pw"
Dim wb as Workbook
Dim ws as Worksheet
Dim rng as Range

と仮設定して・・・

‘ブックのロック/ロック解除

wb.Protect LOCK_PW     'ロック
wb.UnProtect LOCK_PW   '解除

‘シートのロック/ロック解除

If Not ws.ProtectContents Then ws.Protect LOCK_PW , AllowFiltering:=True    'ロック
If ws.ProtectContents Then ws.UnProtect LOCK_PW   '解除

(ロックしてもオートフィルターは使えるようにしといたほうが無難)

‘セルのロック/ロック解除

rng.Locked = True     'ロック
rng.Locked = False    '解除

シートはロックされているかどうか確認するプロパティがあるので、ロックがかかっていなければロックをかけるようにしないと、Excel2013ではロック・ロック解除に時間がかかるので、無駄に時間を食うロジックになってしまう。
セルロックはセルのロックをかけてもシートロックかけてないと有効にはならないので注意。

‘———————————————————

‘セルが数式なのかどうか

If rng.HasFormula Then
    '数式です!
Else
    '数式じゃありません!
End If

SQLServer覚書 日付8桁に、文字を数値に、数値を文字に

前の投稿から結構日数が経ってしまった。
というか、1月以上あいてしまった。

最近、SQLServerに接続してうんたらかんたら・・・というような開発をしている。
面倒だ・・・

DBによって、いろいろ関数がちがうのが困る。
例えば、OracleとかPostgreSQLだと、Now()で取ってこれる現在日時も、SQLServerだとGetDate()。
PostgreSQLだと、カラム名::intとかすればキャストできてしまうわけだが、SQLServerだと、Cast関数か、Convert関数を使う。

どっちが良いかはともかく、揃えてくれ・・・と思う。

さて、日付を8桁のYYYYMMDD形式にする方法。
現在時刻を8桁の文字列にする方法(CONVERT関数)
convert(varchar(8), getdate(), 112)

引数の最後の112ってのが「yyyymmdd」形式という意味。
これが、111だと「yyyy/mm/dd」、110だと「yyyy-mm-dd」になる。
(始めの引数をvarchar(10)にしておかねば・・・)

文字を数値に(CONVERT関数)
convert(int, ‘1234’)

数値を文字に(STR関数)
str(1234)

VBAでADOを利用しているが、数値のままだと文字連結でエラーになってしまった。
なので文字列型にしてから連結するためにSTR関数を使う。

Excelマクロ覚書 グラフを図でコピー

シートコピーとかするとグラフとデータをまるっとコピーできるが、そういうわけにもいかないときもある。
例えば、グラフのデータが別シートにあるとき。
これは困ったものだ、どうしたものか・・・と悩んでいたら、

「図でコピーして図で保存しておけばよいではないか!」

と思い立った。
これなら、グラフの元データの場所を考える必要ないし、ピクチャ形式で保存しておけば、容量もさほどとらないのではと思い、早速マクロを組んでみる。

CopyPictureというプロシージャ(関数)を利用するのだが、貼り付け関数は、シート関数にしかないので、貼り付けたいセルをSelectしてから、シート関数で貼り付けるという、少々バカバカしいというか、わざわざSelectする手間がいるところが嫌なところだ。

とりあえず、組んで走らせてみると、想定通りグラフは図形として貼りついて、オホホホホーーーとか思っていたら、動作検証をしてくださっているお客様から、

「うまくいかないんですよね~」とメールがやってきた。

やってみると、本当にうまくいってない。
グラフのプロットエリアがどんどんずれていって、プロットエリアが小粒になってしまっておる。

なぜじゃ!ナゼにじゃ!!

私が触ってた時はうまくいってたのに・・・と思って色々試すと、うまくいくときといかないときがある。

こういうのが一番困るんだよ。

と思いながら眺めていたら、どうやらシートの表示(ズーム)に影響しているのだと分かった。
解像度とかの絡みなのだろうか。

とりあえず、コピー元シートをアクティブにして、
 ActiveWindow.zoom = 100
とした後で、貼り付け先シートに貼り付けてやると、プロットエリアがずれないで貼りつくようになった。

おそらく、コピー元と貼り付け先のズームを同じにしてやらないと、綺麗には貼りついてくれないのだろう。
やれやれ、まったく困ったものだ。

iPhoneアプリ勉強再開

キックボードに乗ってた子供が交差点に飛び出してトラックにはねられて死んだらしい。
子供やその親には気の毒な話だが、もっと気の毒なのはトラックの運転手だ。
こんなんで人殺し扱いされてはかわいそうだし、ちゃんと法改正して、歩行者にも相応の責任をきっちり負わせるべきだと、私は思う。
(この場合、キックボードを買い与えていた親にも)

自転車もそうだが、あまりにも手軽すぎるために、運転能力(技術と知識)がなくても平気で乗っている人が多いが、その責任は自動車運転と変わりなく取らせるべきだというのが私の考えである。
社会に出るからにはそれ相応の責任が伴うということを子供のころからわからせるのが大人の役目だとも思う。
当然、大人には、さらなる自覚と行動が求められるはずである。

さて、Xcodeだ。
夏のはじめに早くも夏バテして何のやる気も起きなかったのだが、ようやくMacbookを立ち上げてアプリ作成を再開しようという気になった。
この扱いにくい開発環境もStoryboardとObject-Cファイルとの関連付けや、簡単な画面遷移ならチョコチョコっとできるようになった。
値の引き渡しも、とりあえずAppDelegateに入れて・・・みたいのものであればできる。

他の人が1,2週間ぐらいでわかったことを私は半年ほどかけてようやく理解できた。
(なんて軽い脳みそなんだ・・・)

できるようになりだすと、楽しくなってくるのだが、どうせまた(自分にとっては)巨大な壁が立ちふさがってくれそうだ。

今作っているアプリは、インターネットの接続確認と、XMLのパースがうまくできれば!ってところまで来ている。

やっと人に見せられるようなアプリができそうでウレシイ。

Win8.1/iOS/Xcode5

タブレットが欲しいんだけど、iOS7がでる秋までとりあえずは待ち。
Win8.1がどんなんかによって、PCを新しくするのもありかなぁ・・・などとVAIOを物色してみる。
Xcode勉強中だが、Xcode5が出るってので、今まで作ったやつ使えなくなったらどうしよう・・・と焦る。

あぁ、なんかモヤモヤするぅ!

ExcelVBA覚え書 プロシージャ呼出し順

Excelマクロのお勉強。
WorkbookやFormといったオブジェクトにデフォルトで備わっているプロシージャ(メソッド)って、どんな順番で呼び出されるのよ?って思ったので調べてみた。
今更だけど・・・
ちなみにバージョンは2003。

ブックを開いたとき(起動時)
Workbook_Open
Workbook_Activate
Workbook_WindowActivate

※ブックをVisible=FalseにしたときはActivateプロシージャは走らないと思うので、基本はOpenプロシージャに処理を書く。

ブックを閉じるとき(終了時)
Workbook_BeforeClose
Workbook_WindowDeactivate
Workbook_Deactivate

※起動時と同様。

フォームロードしたとき
UserForm_Initialize
フォーム.Showしたとき
UserForm_Layout
UserForm_Activate
フォーム.Hideしたとき
なし
フォームアンロードしたとき
UserForm_QueryClose
UserForm_Terminate

QueryCloseとTerminateの違いは何?って思ったけど、QueryCloseはアンロードの起動処理で、Terminateはホントのアンロード処理という感じ。
つまり、アンロードの起動処理なのでアンロードするかどうかプロシージャ内で分岐できるのがQueryClose。CancelパラメータにTrueを設定するとアンロードを中止できる。
QueryCloseで何事もなければTerminateプロシージャが呼び出されて、アンロード処理の記載ができるようだ。

PostgreSQL覚書 カンマ区切り→縦

つづけて、1つのカラムの中にカンマ区切りでデータが入っていた場合に、
これを縦にする方法。


SELECT regexp_split_to_table(item_cd,’,’) item_cd FROM table_name

item_cdカラムに「a,b,c」と入力されているとすると、出力は

a
b
c
となる。

PostgreSQL覚書 横→縦

財布を落とした。
警察へ行った。
紛失届を作成するのにあれやこれや聞かれて、答えれば答えるほど(なくしたものの大きさに)堪える・・・
って、こんな時にもダジャレが出るぐらいに凹んでる。

さて、仕事しよう。

data1,data2,data3 というカラムがあるとして、それを

data1
data2
data3
と縦に並べたいときのやり方。

SELECT unnest(array[data1, data2, data3]) as data_col
FROM table_name;

PostgreSQL覚書 現在の接続数

PostgreSQLで現在の接続数をみたい場合のSQL文

詳細
SELECT * FROM pg_stat_activity
ORDER BY query_start;

サマリー
SELECT datname, usename, COUNT(*)
FROM pg_stat_activity
GROUP BY datname, usename;

PostgreSQL覚書 型変換して並び替え

文字型のフィールドを数値化して並び替えする場合はキャストするらしい。

ORDER BY cast( [文字型フィールド] as int)

って感じ。
([文字型フィールド] をフィールド名に変える。)

このブログのPostgreSQL情報もどんどん増えてきていい感じだ。

PostgreSQL覚書 日付と曜日

PostgreSQLは配列を使えるので、簡単な書き方が何かあるはずだと思っていたら、やっぱりあった。


SELECT
TO_CHAR(current_timestamp,’YYYY年MM月DD日’) ||
(ARRAY[‘(日)’,'(月)’,'(火)’,'(水)’,'(木)’,'(金)’,'(土)’])
[extract(‘dow’ FROM current_timestamp) + 1] as now_date

“2013年04月18日(木)”

ってな感じで表示される。
便利だなぁ~~~

PostgreSQL 8桁日付の日付加算

8桁で日付を表しているときの日付計算について

下の例では、8桁日付のところを文字列にしているが
 COALESCE(TO_CHAR(20120921,’99999999′),’99991231′)
とか置きかえてやれば、数値でも転用できる。

——————————————

SELECT to_char(to_timestamp(‘20120921′,’YYYYMMDD’) + ’20 days’,’YYYYMMDD’) as add_date;

とすると、結果は “20121011” と返ってくる。

SELECT to_char(to_timestamp(‘20120921′,’YYYYMMDD’) + ’20 days’,’YYYYMM01′) as add_date;

とすると、結果は “20121001” と返ってくるので月初めの日付を取得することができる。

要は、TO_TIMESTAMPメソッドでタイムスタンプ型にしてやることのようだ。
TO_DATEでは計算はできなかった。

[2013/05/09追記]
select to_date(20120921::text,’YYYYMMDD’)
::で型変換(キャスト)してしまえば、もっと楽ってわかった。

PHP覚書 正規表現

はぁ~

正規表現は本当にイヤだ。
便利なんだが、とっかかりにくい。

それはさておき、メモメモ!
phpで値を定義するdefine関数の定義と値をとってきたい!などと思って、とりあえず作ってみた。


$arr1 = preg_split(‘/^define¥(|¥)¥;/’, $buf);
$arr2 = explode(‘,’, $arr1[1], 2);

本当はpreg_split 1回で済ませたいのだが、

define(AAA, 1);
define(ABC, “A,B,C”);

みたいな定義をしているもので、
「1つめのカンマは効いてほしいけど、2つ目以降は見てほしくないの!」
なことをしたい。
だけど、preg_splitでカンマで区切るのは1回だけ!っていう指定をどうやってやるのかわからんかったので、とりあえず、preg_splitで「define(」と「);」 で、

 array( “”, “AAA, 1”, “”)

という感じに分割させて、その後、

できた配列の2つめの文字列(上で言うと、”AAA, 1″)をカンマで2つの配列に分けよ!

ということでexplodeを利用してみた。

もっといいやり方ないかな・・・

PostgreSQL覚書 RETURNING句

私はPostgreSQLが好きだ。
無料だし、機能も結構充実してる。
MySQLのGUI管理画面はいかにも重そうなのだけど、PostgreSQLのはそんなに重くない。
(よく強制終了しているけど)

この間、他の人の書いたソースコードにRETURNING句があった。
一目見ただけで、何のためのものかは分かったのだが、
「こんなことできるんだ・・・」
と衝撃的だった。
INSERT INTO ….. RETURNING A,B
とかにすると、挿入したデータのカラム値を配列で返してくれるそうな。

便利だ!
Nextval()とか、CurVal()とかしなくてもいいのね!
なんて素敵なんだ!

HTML覚書 inputタグIMEモード切替

<携帯>
Docomo、au、Softbankの3社の端末で認識させるためには、istyleとmode属性を使う必要あり。

  1. [漢字] istyle=”1″ mode=”hiragana”
  2. [カナ] istyle=”2″ mode=”hankakukana”
  3. [英数字] istyle=”3″ mode=”alphabet”
  4. [数字] istyle=”4″ mode=”numeric”

携帯で注意することは、maxlengthプロパティ。
バイト数でみるケースと、文字数で見るケースの2通りあるので、漢字・ひらがな入力させる欄については、文字数×2に設定しておかないといけない。

<iOS-safari>
勝手にやってくれること、勝手にやっちゃうことに気を配らないといけない・・・

  1. [数値] type=”numeric” : 日本語/英字切替はしない。0から始まる数値は自動的に0を取り除くので注意。
  2. [TEL] type=”tel” : 先頭0を自動的に外されると困る場合は、数値入力でもこちらを利用する。
  3. [email] type=”email” : 自動的にメールチェックをするので注意。
  4. [PW] type=”password” : 日本語/英字切替はしない。

SVN覚書 hook

SVNやっております。

サーバにインストールできたし、ちゃんとApacheの設定で、HTTP経由で見れるようにもした。
trunkやらbranchesやらフォルダも作ったし、Importで初期ソースの登録にも成功した。
クライアントからはチェックアウトもコミットもできるようになった。
(そのあたりは、また、覚書にして保存しておかねば!)

でも、Hookができない。
Logを吐くのはうまくいったが、Updateできない・・・

で、便利なツール発見。
http://rakusai.org/svnhookgen/index_ja.htmlオンライン版 SVN フックスクリプト「Post-Commit」作成ツール

もう一回チャレンジする!けど、また明日・・・