fc2ブログ

(元)社内SEの徒然なる日記

NetCOBOLのサブルーチン修正でORA-01413発生

サブルーチンだけコンパイル

もう3年ほど前の話ですが、当時サブルーチンの機能を拡張しようとした時に、メインプログラムをリコンパイルせずに実行させたことがあります。
コンパイル公式方式が動的リンクだったのでいけると思ったんですが、甘かったようです。

障害の内容

問題となったサブルーチンは引数の受け渡しのための専用のソースを使用しています。
メインプログラムとサブプログラムで、このCOPY句を使用してパラメータの受け渡しをします。

サブルーチンの機能拡張のために、COPY句に項目を追加、サブルーチンも修正してコンパイルして実行したのですが、OracleのInsert文でCOPY句に追加した項目が原因で異常終了しました。


ORA-01413: パック10進数のバッファの値が無効です。


障害発生時の状況

下記が修正したCOPY句の内容です。
11/25 の追加個所が障害発生時の修正個所です。

【COPY句】

01 ()-PARM.
10 ()-KIDOU-KBN PIC X(001). *> 起動区分
10 ()-SOUSINMOTO-CODE PIC X(006). *> 送信元担当者コード
10 ()-SOUSINSAKI-CODE PIC X(006). *> 送信先担当者コード
10 ()-GYOUMU PIC X(040). *> 業務名
10 ()-RENRAKU1 PIC X(040). *> 連絡内容1
10 ()-RENRAKU2 PIC X(040). *> 連絡内容2
10 ()-KEKKA PIC 9(001). *> 結果
10 ()-ERRORCODE PIC X(002). *> エラーコード
* 2009.11.25 ADD START ---
10 ()-COMMIT PIC X(001). *> コミットフラグ(0:COMMITする 1:COMMITしない)
10 ()-CHARGE-CODE PIC X(006). *> 受付担当者コード
10 ()-ORDER-NUM PIC X(008). *> 伝票番号
10 ()-KUBUN PIC S9(012)V9(3) COMP-3. *> 区分(1:入荷 2:出荷)
10 ()-MANAGER-NUM PIC S9(012)V9(3) COMP-3. *> 管理番号
10 ()-DETAIL-NUM PIC S9(012)V9(3) COMP-3. *> 明細番号
10 ()-ORDER-METHOD PIC X(001). *> 発注方式
* 2009.11.25 ADD END -----


下の7つの項目(コメントの2009.11.25の範囲内)を追加しています。
次にサブルーチンに、追加した項目をホスト変数に設定する処理を追加します。
H-で始まるのがホスト変数です。

【サブルーチン】

MOVE P1-ORDER-NUM TO H-ATRCHREXP01. *> 伝票番号
MOVE P1-CHARGE-CODE TO H-ATRCHREXP02. *> 受付担当者コード
MOVE P1-ORDER-METHOD TO H-ATRCHREXP03. *> 発注方式
COMPUTE H-ATRNUMEXP01 = P1-MANAGER-NUM. *> 管理番号
COMPUTE H-ATRNUMEXP02 = P1-KUBUN. *> 区分(1:入荷 2:出荷)
COMPUTE H-ATRNUMEXP03 = P1-DETAIL-NUM. *> 明細番号


異常終了したInsert文は下記の内容です。
追加した項目を設定してInsert文を実行させます。

【INSERT文(一部抜粋)】

*-- テーブルへの登録
EXEC SQL
INSERT INTO ABCD
(TESTAA,




TESTBB
)
VALUES(RTRIM(:H-TESTAA),




* -- 2009.11.25 ADD START ---
RTRIM(:H-ATRCHREXP01), -- 伝票番号
RTRIM(:H-ATRCHREXP02), -- 受付担当者コード
RTRIM(:H-ATRCHREXP03), -- 発注方式
* -- 2009.11.25 ADD END -----




* -- 2009.11.25 ADD START ---
:H-ATRNUMEXP01, -- 管理番号
:H-ATRNUMEXP02, -- 区分(1:入荷 2:出荷)
:H-ATRNUMEXP03, -- 明細番号
* -- 2009.11.25 ADD END -----




''
)
END-EXEC.


メインプログラムは未修正のまま実行させます(コンパイルもしません)。
実装は、下記のようにします。

メインプログラム

* *> 引数設定
MOVE "2" TO P1-KIDOU-KBN. *> 引数.起動区分(1:オンライン、2:バッチ)
MOVE CS-CHRID TO P1-SOUSINMOTO-CODE. *> 引数.送信元担当者コード
MOVE "データ調査" TO P1-GYOUMU. *> 引数.業務名
MOVE "エラーメッセージ1です" TO P1-RENRAKU1.
MOVE "エラーメッセージ2です" TO P1-RENRAKU2.
*
* *> サブルーチン実行
CALL "TEST999" USING P1-PARM.
*
* *> エラートラップ
IF P1-ERRORCODE NOT = "00"
DISPLAY "サブルーチンエラー"
END-IF.


これを実行したところ、前述のエラーが発生しました。

障害の切り分け

下記の手順で、障害の発生個所を特定しました。

① メインプログラムをリコンパイルして再処理したのですが、同じエラーが発生しました(ーー;)

② どの引数でエラーが発生しているのか、トライ&エラーで探索。数値項目がエラー個所と特定。

③ 引数の値を、ホスト変数に設定する処理を MOVE文 から COMPUTE文 に変更。同じエラー発生。

④ DISPLAY文で、引数の数値項目と設定後のホスト変数の値をログ出力。 +000000000000000 が表示。

⑤ 引数の初期化が原因と想定して、引数の数値項目が LOW-VALLUE だったら ZERO にするロジックを追加。コンパイルエラー。( 数値項目 = LOW-VALUE の比較式は使えない )

⑥ メインプログラムを修正。引数を起動側で初期化( INITIALIZE文 を発行)。正常に実行完了。
  ただし、サブルーチンを使用しているPGが余りにも多い( 200本近い )ので別の手段を検討。

⑦ サブルーチン側で、数値項目が ZERO であれば ZERO を設定するロジックを追加。
  正常終了することを確認。
  ...しかし、このロジックで動くということは、メモリの割当とかその辺りに何かあるということだろうか。
  なんだかなぁ(-_-)

対応方法

障害切り分けで確認した通り、サブルーチン側にZERO であれば ZERO を設定するロジックを追加しました。

【追加内容】

* 引数の補正
IF P1-KUBUN = ZERO
COMPUTE P1-KUBUN = ZERO
END-IF.
IF P1-MANAGER-NUM = ZERO
COMPUTE P1-MANAGER-NUM = ZERO
END-IF.
IF P1-DETAIL-NUM = ZERO
COMPUTE P1-DETAIL-NUM = ZERO
END-IF.


あれから3年たって思う

あれから3年たって、当時の資料からこの記事を起こしているのですが、いろいろと考えさせられる事例ですね。
障害時切り分けの中で、メインプログラムのリコンパイルをしても状況が再現したということから考えると、「 WORKING STARAGE SECTION」で宣言した変数を初期化しないで使用すると、同じ現象を発生させられそうですね。
こうして考えると、「変数は初期化してから使用する」っていう作法がとても大切だということが分りますね。
たしか、COBOLの言語仕様も、初期化していない変数の値は保障していなかったはずなので、奇妙な現象が発生するのは無理もないかもしれませんね。

それにしても、当時はこれで納得したんですけど、今にして思えば危険なことをしたように思います。
現在まで、特に障害にはならずに動作してるので、まぁ問題なかったのかもしれませんが、気合い入れて200本のメインプログラムを全部直した方がよかったかも知れません。
本数は多くても、1行追加するだけですしね。


余談

当社の運用ルールとしてソースを修正した場合は、日付付きのコメントを付けることになっています。
現在はsubversionで資産管理はしているので、無用と言えばその通りなのですが、昔の修正分との整合性を保つために続けています。
「ソースが汚くなる」とか「可読性が云々...」とか「追えなくなる」とか騒ぐ人もいるのですが、私の答えは「サンデープログラマじゃあるまいし、気合い入れて追えよ」だったりします。
...少し傲慢ですかね?


前回:NetCOBOLのコンパイルエラー集
次回:NetCOBOLでロードモジュールからSQLを取り出す
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---


スポンサードリンク

PageTop

LinkStation HD-HG160LANを分解してみた

私の勤め先の某拠点に設置されていたLinkStation(HD-HG160LAN)が使えなくなりました。
エラーランプを確認すると、どうやらファンが破損しているようです。

手元に同じ型のLinkStationがあるので、ファンを交換すれば使えるようにならないかと思い、とりあえず分解してみました。

ファンと同じ面にあるネジをドライバーで外します。
IMG_0734.jpg

足の部分のやつを「UNLOCK」の方にスライドして外します。
IMG_0737.jpg

本体の灰色っぽいのをスライドさせます。
IMG_0735.jpg

こんな感じで指を掛けて外します。
IMG_0736.jpg

ここからが難題です。
上と下に2つずつある留め具を何とかして外します。
IMG_0732.jpg

ちなみに、私は片方の爪にドライバーを突っ込んで固定して、むりくり開きました。
IMG_0733.jpg

上手くはずれれば、こうやってパカッと開きます。
IMG_0729.jpg

電源コードをずらします。
IMG_0726.jpg

これで、ファンが本体から外れます(線はまだ繋がってます)。
IMG_0727.jpg

基盤の端っこにあるネジ(4本)を外します。
IMG_0722.jpg

電源入れる部品を外します。
IMG_0723.jpg

これで基盤を動かせます。
IMG_0724.jpg

とりあえず、各ランプを光らせている透明な部品を外します。
IMG_0725.jpg

これで、カパッと基盤が外れます。
IMG_0728.jpg

外れました。
IMG_0720.jpg


後は、ファンから伸びた線が、基盤とかにいくつか刺さってるので、全部抜きます。
もう一つのLinkStationも、同じ方法で分解してファンを入れ替えたところ、無事に復活しました。
これでデータは抜けるので、あとはどうでも良いです。

なお、ファンの修理はしません。
こんな骨董品を修理するくらいなら、素直に新しいの買った方がコスト的にも良いと判断しました。

組立は、逆の手順でOKです。
...なんですが、実は分解以上に手こずりました。
なんか、爪が上手くあわさらないんですよね。
どうやら私には、こういう手先を使う作業のセンスは無いようです。


スポンサードリンク

PageTop

NetCOBOLのコンパイルエラー集

コンパイルエラー

思わず「はぁ?」と唸ったコンパイルエラーを紹介します。
...誰かの役にたつとは思いませんけどね。

暗黙カーソル指定時のSELECT文エラー

あるテーブルからデータを抽出するSELECT文が何故かプリコンパイルでエラーになりました。
実際のSQLはこんな感じです。

EXEC SQL
SELECT
REPLACE(NVL(FGRCD ,' '), '"' , '''' ) ,
NVL(NUMMGR , 0 )
INTO
:H-FGRCD ,
:H-NUMMGR
FROM ABCD
WHERE FGRCD = :H-IN01-FGRCD
AND NUMMGR = :H-IN01-NUMMGR
END-EXEC.

最終的にはCSVに変換する処理なので、REPLACEを使用してダブルクォートをシングルクォートに置き換えているのですが、プリコンパイラはREPLACE文が気に入らなかったようです。
ところが、まったく同じSQLを明示カーソルを使用して記述すると、エラーにならなかったりします。

思わず「はぁ?」とか呻いてしまいました。
まぁ、システム開発ではよくある事ですけどね。

解決策は、明示カーソルを使用するか、動的カーソルを使用するかの二択だったのですが、この時は動的SQLに書き換えることにしました。
なれると、動的SQLってすごく便利。

SQLコメント -- 指定時のエラー

プリコンパイルでこんなエラーが発生しました。

行337、列72でエラーが発生しました。ファイル/opt/testdir/cob/main/TEST100.pco
337 003370 SET INI = :H-INI , -- イニシャル
337 .......................................................................1
337 PCB-S-00400, 記号"-"が見つかりました。 次のうちの1つが入るとき:
( id
string REPLACE DATE COUNT EXTRACT INTERVAL TIME TIMESTAMP
TRIM AVG MAX MIN SUM STDDEV VARIANCE

しばらくは、何が何やら分らなかったのですが、落ち着いてよく見て見るとSQLのコメント「 -- イニシャル 」の -- がB領域とプログラム識別番号領域( 72列目と73列目 )に跨っていました。
プリコンパイラはこれをエラーとしたようです。
...まぁ、これは私が悪いですけどね。

素直に、1文字ずらして解決しました。

行内コメントで発生したエラー

EXEX SQL ~ END-EXEC. の間で行内コメント( *> コメント ) を使用したのですが、コンパイル時に、下記のように大量のエラーが吐き出されました。

** 診断メッセージ ** (TEST200)

JMN1123I-S 2914,2915,2916 許されない語'VARYING'が現れました.次の認識できる句,段落,節または部まで無効になります.
JMN1545I-S 2922,3098,3314,3402,3514 作業場所節中または連絡節中には,'BEGIN DECLARE SECTION'および'END DECLARE
SECTION'以外は指定できません.
JMN1278I-S 3512 BEGIN DECLARE SECTION文が指定されずに,END DECLARE SECTION文が指定されています.
JMN1576I-S 4070,4073,4076,4136,4139,4230,4235,4240,4259,4815,4874,5082,5101,5798,5851,5931,5950,6232,6284,6381,6400,
6738,6789,6797,6815,6848 このシステムでは,'SQL機能'は使用できません.
JMN2503I-S 4082 利用者語'SQLCODE'が定義されていません.
JMN2600I-S 4082 条件中のオペランドに誤りがあります.
JMN2557I-S 4082 IF文の書き方が不完全です.
JMN2510I-S 4084 対応しないEND-IFが指定されています.END-IFは,無効となります.
JMN2503I-S 6794 利用者語'SQLCA'が定義されていません.
JMN2557I-S 6794 CALL文の書き方が不完全です.
JMN2503I-S 6837 利用者語'USERNAME-LEN'が定義されていません.
JMN2557I-S 6837,6840,6843 COMPUTE文の書き方が不完全です.
JMN2503I-S 6839 利用者語'USERNAME-ARR'が定義されていません.
JMN2557I-S 6839,6842,6845 MOVE文の書き方が不完全です.
JMN2503I-S 6840 利用者語'PASSWD-LEN'が定義されていません.
JMN2503I-S 6842 利用者語'PASSWD-ARR'が定義されていません.
JMN2503I-S 6843 利用者語'DBSTRING-LEN'が定義されていません.
JMN2503I-S 6845 利用者語'DBSTRING-ARR'が定義されていません.

JMN2540I-W 6807 EXIT文を含む段落は,手続き名とEXIT文だけで構成されていなければなりません.EXIT文は,無効となります.

最大重大度コードは S で,翻訳したプログラム数は 1 本です.


ここまでエラーを吐いておいて、実際のエラー個所は下記の一行です。

000830 EXEC SQL INCLUDE TEST999.CBL END-EXEC. *> コネクト用変数


「*> コネクト用変数」を削除すると、コンパイルが通りました。
どうやら、EXEX SQL ~ END-EXEC. の範囲内では、行内コメントは使用しない方が無難なようです。
ただ、コメントを80BYTE以降に記述すると、コンパイルが通るようになりました。
いろいろ考えさせられますね。



前回:NetCOBOLで動的SQLを使ってみる
次回:NetCOBOLのサブルーチン修正でORA-01413発生
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---


スポンサードリンク

PageTop

NetCOBOLで動的SQLを使ってみる

動的SQLってなに?

これまでに記載したSQLの実行方法では、SQL文自体が固定されていたため、できる事と言ったら、抽出条件の値を変更する位で、条件に応じでSQL文を書き換えるような処理はできませんでした。

動的SQLを使うことで、文字通りプログラムの実行中にSQL文を編集することが出来るようになります。

動的SQLの使用方法

基本的な考え方は、カーソルを使った抽出方法と同じです。
今回は、「習うより慣れろ」の格言に基づきサンプルを提示します。

まず、WORKING-STORAGE SECTION. にSQL文格納用のホスト変数を準備します。

WORKING-STORAGE SECTION.
*
* ホスト変数
* 埋込みSQL宣言節の開始
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
* 動的SQL
01 H-SQL-STRING PIC X(20000).
01 H-HEAD-CDZIP PIC X(10).
01 H-HEAD-ADR1 PIC X(10).
* 埋込みSQL宣言節の終了
EXEC SQL END DECLARE SECTION END-EXEC.


PROCEDURE DIVISION. で動的SQLのカーソル定義を行ないます。

* *> 動的SQLの設定クリア
MOVE SPACE TO H-SQL-STRING.
*
* *> 動的SQL作成
STRING
"SELECT " DELIMITED BY SIZE
"NVL(HEAD.CDZIP, ' '), " DELIMITED BY SIZE
"NVL(HEAD.ADR1, ' ') " DELIMITED BY SIZE
"FROM " DELIMITED BY SIZE
"HEAD " DELIMITED BY SIZE
"WHERE " DELIMITED BY SIZE
" HEAD.TESTITEM = '200' " DELIMITED BY SIZE
INTO H-SQL-STRING
END-STRING.
*
* *> 動的SQLを用意します
EXEC SQL
PREPARE STCU01 FROM :H-SQL-STRING
END-EXEC.
*
* *> 動的カーソル宣言を行ないます
EXEC SQL
DECLARE CU01 CURSOR FOR STCU01
END-EXEC.
*
* *> 動的カーソルを開きます(SQLの実行)
EXEC SQL
OPEN CU01
END-EXEC.


あとは普通のカーソルと同じで、FETCHでデータを取得して、最後にカーソルをクローズします。

EXEC SQL
FETCH CU1
INTO
:H-HEAD-CDZIP ,
:H-HEAD-ADR1
END-EXEC.

* カーソルクローズ
EXEC SQL
CLOSE CU1
END-EXEC.


埋込みSQLとの違い

まず、SQL実行の前処理としてPREPARE文の記述が必要です。

構文

PREPARE <SQL文識別子> FROM <SQL文変数>

「SQL文識別子」は、実行するSQLを識別するための名前です。
上記のサンプルでは「STCU01」となっています。
カーソル名と同じく、WORKING-STORAGE SECTIONで定義する必要はありません。

次に、PREPARE文で用意した動的SELECT文のカーソルを定義します(動的カーソル宣言)。

構文

DECLARE <カーソル名> CURSOR FOR <SQL文識別子>


あとは、特に変わりません。

追記

サンプルではPROCEDURE DIVISIONでSTRINGを使用して直接SQL文を作成しましたが、WORKING-STORAGE SECTIONで準備したり、あるいはテキストファイルにSQL文を記述しておいてREADで読み込むといった実装も考えられます。

他の利点として動的SQLの場合、プリコンパイラでSQLのチェックが行われないという点があります。

どこかで書いたかもしれませんが、SQL*PLUSとかでは実行できるSQLが、プリコンパイラではエラーになる場合があります。
このような時に、動的SQLを使うことで問題を回避することが出来ます。


前回:NetCOBOLでのコミットとロールバックの考察
次回:NetCOBOLのコンパイルエラー集
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---


スポンサードリンク

PageTop

NetCOBOLでのコミットとロールバックの考察

コミットしないとどうなるか?

1本のCOBOLプログラムがそのまま1セッションに対応するので、コミットせずにプログラムが終了されると、ロールバックが実行されたのと同じ結果になります。

複数トランザクション使いたい時は?

複数トランザクションをしたい時は、トランザクションを終了する所でコミットかロールバックを実行してやればOKです。
意識してトランザクションの開始と終了を記述しないといけない言語に比べると、この点は楽ですね。

暗黙のコミット

COBOLに限ったことではないのですが、DDL文が実行されると暗黙的にコミットが実行されます。

例えば、下記の処理をCOBOLで実装したとします。

1. INSERT INTO TDKY(TESTITEM) SELECT TESTITEM FROM ABCD

2. TRUNCATE TABLE ABCD

3. INSERT INTO TDKY(TESTLIST) SELECT TESTLIST FROM EFGH WHERE STCAN = '1'

4. ROOLBACK


1.と3.で、TDKYテーブルに対してINSERTを実行して、4.でロールバックします。
しかし、2.でTRUNCATE(DDL文)が実行されたため、この時点で暗黙的なコミットが実行されます。
その結果、4.のロールバックで取消されるのは、3.のINSERTのみになります。


前回:NetCOBOLでSQLのエラーを確認する
次回:NetCOBOLで動的SQLを使ってみる
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---


スポンサードリンク

PageTop

NetCOBOLでSQLのエラーを確認する

エラー処理ってなんぞや

NetCOBOLでは、SQLの実行でエラーが発生してもそのまま処理が続行される性質があります。
なので、何もしなければSQLでエラーが発生してもCOBOL自体の処理は続けて実行されてしまいます。

そこで、SQLのエラー状態をプログラム側でチェックする必要があります。

エラーチェックにはSQLCAのSQLCODEの値を判定する方法と、WHENEVER文を使用する方法がありますが、WHENEVER文を使用する方がまっとうと思われるので、こちらの話のみ書いておきます。

WHENEVER文

WHENEVER文を使用することで、SQL実行時にエラーが発生したときに自動的にエラー処理を行うことが出来ます。
取得できるのは「異常・警告・データ無し」の3つの状態で、それぞれの状態に対してエラー処理を記述できます。

【構文】

EXEC SQL
WHENEVER   「状態」
「アクション」
END-EXEC.


状態

状態は、下記の3つの何れかを指定できます。

・SQLERROR
致命的なエラーを検出した場合。SQLCODEには負の値が設定されます。

・SQLWARNING
警告となった場合。詳細はSQLCAを見ないと解らないが、続行可能である場合もあります。

・NOT FOUND
SQLの実行結果が0件の時に発生します。フェッチで最終行に達した時もこの状態となるので、明示カーソルを使用して処理を行う時は、この状態を検出することでフェッチの終了を判断します。(SQLCODEには+1403が戻される)

アクション

・CONTIMUE
「状態」チェックをオフにします。WHENEVER文を設定していない状態に戻すという事です。

・DO CALL
指定したサブプログラムを実行します。
サブプログラムの実行が終了すると、失敗したSQLの次の文が実行されます。

・DO PERFORM
指定したCOBOL節、段落が実行されます。つまり、通常のPERFORM文と同じ動作です。
節の最後まで実行した後に、失敗したSQLの次の文が実行されます。

・GOTO 又は GO TO
指定した段落または節に移動する。

STOP
プログラムを終了する。COMMITされていない作業はロールバックされる。

WHENEVER文による異常時の実行例

下記のソースを例として、SQLエラートラップの記述方法を解説します。

MAIN-RTN SECTION.
*A.エラー宣言
EXEC SQL WHENEVER SQLERROR
DO PERFORM SQLERROR-RTN
END-EXEC.

*B.SQL実行
EXEC SQL
SELECT NVL(NMDPT , ' ' ) INTO :H-NMDPT FROM MDPT
WHERE CDCOM = RTRIM(:H-CDCOM) AND CDDPT = RTRIM(:H-CDDPT)
END-EXEC.

*C.エラートラップ
IF WK-ERR-FLG = "1" THEN
DISPLAY ERR-MSG
GO TO ERR-STOP
END-IF.

MAIN-EXIT.
EXIT.

*D.エラー処理
SQLERROR-RTN SECTION.
MOVE "1" TO WK-ERR-FLG.
EXIT.

*E.強制終了処理
ERR-STOP.
EXEC SQL ROLLBACK WORK RELEASE END-EXEC.
STOP RUN.


上記ソース中のBで致命的なエラーが発生した場合、下記の順で処理が実行されます。

【処理の遷移】

  1.Bでエラー発生!
  2.Dの異常処理を実行
  3.Dの実行後、Bの次の分であるCを実行
  4.Dでエラーフラグが設定されているため、Eが実行されて処理が終了する

NOT FOUNDを使用した処理

明示カーソルを使用したSELECT文で、選択された全ての行を順次処理するサンプルです。

【使用例】

PROCEDURE DIVISION.

MAIN-RTN SECTION.

EXEC SQL WHENEVER NOT FOUND
DO PERFORM NOT-FOUND-RTN
END-EXEC.

< 初期処理を記述する(ファイルIOやORACLE接続など) >

EXEC SQL DECLARE TEST
CURSOR FOR
SELECT CDITM ,
NVL(CDUNT , ' ' )
FROM MITM
END-EXEC.

EXEC SQL OPEN TEST END-EXEC.

PERFORM UNTIL END-FLG = "END"
PERFORM LOOP
END-PERFORM.

<  終了処理を記述する  >

STOP RUN.

MAIN-RTN-END.
EXIT.

LOOP SECTION.

MOVE "0" TO FLG-SQL-WHENEVER.
EXEC SQL FETCH TEST
INTO :H-CDITM ,
:H-CDUNT
END-EXEC.

IF FLG-SQL-WHENEVER = "2"
MOVE "END" TO END-FLG
ELSE
MOVE H-CDITM TO OUT-CDITM
MOVE H-CDUNT TO OUT-CDUNT
WRITE OUT-REC
END-IF.

LOOP-END.
EXIT.

NOT-FOUND-RTN SECTION.
MOVE "2" TO FLG-SQL-WHENEVER.
NOT-FOUND-RTN-EXIT.
EXIT.


エラー処理の設定順(すごく大事)

WHENEVER文の使用にあたって、最も注意しなければならないことは「複数のWHENEVER文が設定されていた場合、ソースの記述で上にあたる設定が使用される」ということです。
言葉を変えると、「ロジックの順番ではない」ということです。

なにを言っているか分らないと思うので、実際にサンプルをご覧ください。

CNTL-RTN SECTION.
* A.SQL例外宣言
EXEC SQL WHENEVER SQLERROR
DO PERFORM SQLERROR1-RTN
END-EXEC.
*
* B.SQL-RTNルーチンを実行
PERFORM SQL-RTN.
*
* C.SQL文を実行
EXEC SQL
SELECT NVL(NMDPT , ' ' ) INTO :H-NMDPT FROM MDPT
WHERE CDCOM = RTRIM(:H-CDCOM)
END-EXEC.
*
STOP RUN.
CNTL-EXIT.
EXIT.
*
* D.SQL例外宣言
SQL-RTN SECTION.
EXEC SQL WHENEVER SQLERROR
DO PERFORM SQLERROR2-RTN
END-EXEC.
SQL-EXIT.
EXIT.
*
* E.SQLイレギュラー処理1
SQLERROR1-RTN SECTION.
MOVE "1" TO FLG-SQL-WHENEVER.
SQLERROR1-RTN-EXIT.
EXIT.
*
* F.SQLイレギュラー処理2
SQLERROR2-RTN SECTION.
MOVE "9" TO FLG-SQL-WHENEVER.
SQLERROR2-RTN-EXIT.
EXIT.


上記のサンプルを実行した時に、C のSQL文でエラーが発生した時に実行されるエラー処理は、EかFかという話です。
COBOLのロジックで考えると、最後に実行されたWHENEVER文はFを実行するようにしているので、Fが実行されると思うかもしれませんが、実際にはEが実行されます

ロジックの順番じゃないっていうのは、こういう事です。
今一つ釈然としませんが、たぶんプリコンパイルを実行した時にCOBOL自体のロジックまで判断できないってことなんでしょうかね?
やっぱり、言語の設計時に想定していなかった機能を追加しようとすると、所々に無理がでるんでしょうね。

前回:NetCOBOLでSQL文を使ってみた
次回:NetCOBOLでのコミットとロールバックの考察
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---



スポンサードリンク

PageTop

NetCOBOLでSQLを実行してみる

単一行を返すSELECT文

SELECT文の実行においては、一般的なSQL句が使用できます。


EXEC SQL
SELECT NMWRH
INTO :H-AAA-NMWRH
FROM MAAA
WHERE CDWRH = '110'
END-EXEC.

上記のSQLは、MAAAテーブルからCDWRHが'110'であるレコードから、NMWRH列をホスト変数「H-AAA-NMWRH」に格納しています。
受け取る項目が複数の場合はカンマ(,)で区切って指定します。

SELECT文の実行結果が2件以上になる場合はエラーが発生するので、この方法で抽出する場合はPrimaryKeyのように、確実に結果が1件(か0件)になるようにWHERE句に条件を設定する必要があります。

INSERT・UPDATE・DELETE文

INSERT・UPDATE・DELETE文のそれぞれの書き方は、SELECT文と同じ要領で記述できます。


EXEC SQL
UPDATE MITM SET CDUNT = :H-MITM-CDUNT
WHERE MITM.CDITM LIKE '0%'
AND MITM.CDMKR = :H-MITM-CDMKR
END-EXEC.


上記のSQLは、MITMテーブルからCDITMが0から始まり、かつCDMKRが
ホスト変数H-MITM-CDMKRと一致する行のCDUNTをホスト変数H-MITM-CDUNTで更新しています。

見てのとおり、EXEC SQLとEND-EXECで囲っていることとホスト変数の使用以外は通常のSQLと同等になります。

複数行を取得するSELECT文

複数行を取得するSELECT文を発行する場合は、カーソルというものを使います。
...実際には、1件検索でも使用しているんですけどね。

カーソルとは

カーソルと呼ばれる識別子を使用すると、SQL文に名前を付けて処理を制御することが出来ます。

具体的には次の処理が出来ます。

  ① 問合せによって戻された最初の行以後の処理

  ② 現在どの行が処理されているかの追跡と記憶


カーソルの定義と使用の概略は、こんな感じになります。

  ① DECLARE文を使用してカーソルに名称をつけて問合せに関連付ける。

  ② OPEN文で問合せを実行する。

  ③ FETCH文を使用して②の問合せ結果から1行ずつ取り出す。

     FETCHは全ての行が取り出されるまで繰り返し実行できる。

  ④ CLOSE文によってカーソルの使用を禁止する。


静的SQL文のカーソルは明示的なカーソルと暗黙的なカーソルの2種類存在します。

  ① 明示カーソル  ・・・ OPEN、FETCH、CLOSEの3つの処理を全て記述して行う。

  ② 暗黙カーソル  ・・・ 一文でOPEN、FETCH、CLOSEの全ての処理を行う方法。

                 INTO文を使用するSELECT文、データ定義文やDML文で暗黙的に

                 カーソルが使用されている。


カーソルの宣言(DECLARE文)

DECLARE文でカーソルを定義します。
実際に実行するSQL文もここで記述します。

【制限事項】

① カーソル名を他の「DATA DIVISION」 等で記述してはならない。

② カーソル名にハイフンは使用不可

③ カーソル名は18文字まで


【構文】

EXEC SQL DECLARE 「カーソル名」
CURSOR FOR
「SELECT文」
END-EXEC.


カーソルのオープン(OPEN文)

DECLARE文で指定した問合せを実行します。

【構文】

EXEC SQL
OPEN 「カーソル名」
END-EXEC.


カーソルからのフェッチ(FETCH文)

問合せの実行結果から行を取り出して指定したホスト変数に格納します。
これが、テキストファイル読込のREADに相当する処理になります。
最終行の判断(AT ENDに相当するもの)については、エラー処理(http://harikofu.blog.fc2.com/blog-entry-53.html)にて説明します。

【構文】

EXEC SQL
FETCH 「カーソル名」
INTO ホスト変数
END-EXEC.


カーソルのクローズ

行のフェッチ終了後に、カーソルをクローズしてオープンによって取得していたリソースを開放します。

【構文】

EXEC SQL
CLOSE 「カーソル名」
END-EXEC.


追記

バージョンにもよるのかもしれませんが、複雑なSQLはプリコンパイルでエラーになる事がありますので、NetCOBOLからのSQL発行ではシンプルなSQLにすることをお勧めします。
どうしても複雑なSQLを使いたい場合は、動的SQL(記述予定)というものを使って下さい。

前回:NetCOBOLとOracleのデータ型の関係
次回:NetCOBOLでSQLのエラーを確認する
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---

スポンサードリンク

PageTop

札幌のクリームの甘くないケーキ屋さん

ル・シード

札幌白石区のケーキ屋さんル・シード。
知り合いに聞いて試してみました

買ったのは、イチゴショートとモンブランです。
IMG_0757.jpg

ショートケーキ

まずは、イチゴショートから食べてみます。
見た目は普通、イチゴとスポンジは特筆すべき点はないのですが、クリームが甘くない、くどくない。
というか、クリームだけ食べると味がしない。
結果、甘さ控えめのさっぱりしたショートケーキになっています。
強い甘さを求めているならNGですが、生クリームが苦手とか、甘さ控えめが好みの人にはお勧めですね。

モンブラン

続いて、モンブランを食べてみます。

スポンジの上に、たっぷりのモンブラン。
むぅ。非常にクドイです。
さっきのショートケーキが甘さ控えめだったので、薄味のお店かと思っていのですが、大間違いだったようです。
モンブランクリーム(←正式名称が分らんので、こう書きます)の量がたっぷりの上に、味が濃いです。
スポンジと一緒に食べているのですが、正直、クリームの味しかしません。

これは、どうなんだろ?
個人的には趣味じゃないのですが、味のきついモンブランが好きなら、ありなんですかね?

終わりに

結果的には1勝1敗って感じですね。
今度、機会があったら別の種類のケーキも試してみます。

ちなみに、スタンプカードを貰いました。
IMG_0758.jpg

期限がないのは、ありがたいですね。
たまに、現実的にたまる訳がない期限を切っているスタンプカードもありますからね。

スポンサードリンク

続きを読む

PageTop

NetCOBOLとOracleのデータ型の関係

データ型

COBOLとORACLEのデータ型の関係について、わかっている範囲で記述します。
とはいえ、わかっているのはVARCHAR2、NUMBER、DATEの3つだけなので、あまり役には立たないかと。
もちろん、教科書的な意味では他の型との対比も知ってるんですけど、実際に試したのはこの3つだけだったりします。

文字と数値

OracleのVARCHAR2はXタイプ、NUMBERはS9タイプになります。

■ COBOL ■ ORACLE
03 H-CDITM PIC X(030). CDITM VARCHAR2(30)
03 H-CDMKR PIC X(005). CDMKR VARCHAR2(5)
03 H-NUMITMORD PIC X(030). \ NUMITMORD VARCHAR2(30)
03 H-NUMITMINSMKR PIC X(030). === \ NUMITMINSMKR VARCHAR2(30)
03 H-CDCTGLRG PIC X(002). === / CDCTGLRG VARCHAR2(2)
03 H-CDCTGMDL PIC X(002). / CDCTGMDL VARCHAR2(2)
03 H-CDCTGSML PIC X(002). CDCTGSML VARCHAR2(2)
03 H-NMITM PIC X(080). NMITM VARCHAR2(80)
03 H-STD PIC X(060). STD VARCHAR2(60)
03 H-PRCSTD PIC S9(012)V9(2) COMP-3. PRCSTD NUMBER(14,2)


文字型(VARCHAR2とXタイプ)は、見ての通り同じサイズを指定してやればOKです。

数値型(NUMBERとS9タイプ)はちょっと注意が必要です。
COBOLとOracleの数値型のサイズの定義方法が違います。
上記の例では、S9(012)V9(2) は、読んだ通り『整数部12桁、小数部2桁』になります。
一方で、NUMBER(14,2)は、『桁数の総サイズが14桁で、そのうち2桁が小数部』となります。

初めてOracleを触った時、この定義方法に凄い違和感を感じました(私だけか?)。

もう一つの注意点は、必ず『 S9タイプで定義して、COMP-3を付ける 』です。
COBOL屋なら当然知っていると思いますが、COMP-3はパック10進数です。
理屈は分らないのですが、これを付けないとNUMBER型の値を正しく転記してくれませんでした。
ちなみに、S9タイプを9タイプにしても、奇妙な動作をしました。
という訳で、NUMBER型の場合は、S9タイプでCOMP-3付きになります。

日付・時刻型

日付型はXタイプで受け取る事になります。
というのも、COBOLには日付型など無いので、Xタイプで受けざるえないんでしょうね。

■ COBOL ■ ORACLE
03 H-STRDATE PIC X(0020). -> STRDATE DATE


下記は、実際に日付型のSTRDATEを取得するSELECT文のサンプルです。
見ての通り、日付型だからって特に意識する必要はないようです。

EXEC SQL
SELECT
PARA
,NVL(STTFG , ' ') --*> 状態フラグ
,STRDATE --*> 日時
INTO
:H-PARA
,:H-STTFG --*> 状態フラグ
,:H-STRDATE --*> 日時
FROM ABCD
WHERE IDTJOB = RTRIM(:H-IDTJOB)
END-EXEC.


どうやら、SELECT文の実行時にTO_CHARで自動変換してくれるようです。
逆にUPDATEやINSERTの時には、TO_DATEで自動変換されるらしいですが、こちらはテストしてないんで本当かどうかわかりません。
Xタイプを20BYTEにしたのは、自動変換で最大長になりそうな「 TO_CHAR(STRDATE, 'YYYY-MM-DD HH24:MI:SS') 」が実行された時の桁数が19BYTEなので、それ以上で切りの良い数字にしてみました。

まぁ、これだけ取ってれば十分でしょ。

前回:NetCOBOLでSQLCAを使ってみる
次回:NetCOBOLでSQL文を使ってみた
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---

スポンサードリンク

PageTop

札幌市白石区の美味しいピザ屋さん

安くて美味しいピザが食べたい

ピザが好きで、よく宅配ピザを頼んでました。
外食っていう手もあるんですけど、自宅でビールのみながら静かにたのしみたいんです。

テンフォー、ピザハット、ピザーラ、ドミノピザ、ストロベリーコーンズなどなど、いろんな店を試してみましたが、どれも今ひとつニーズにあいませんでした。
そもそも値段が安くても2,000円位から始まって、高いのだと4,000円近くなるので、気軽に買えない。
さらに、そこまで払うわりには、それほど美味しいと思わない。

かといって、他に当てがある訳じゃないので、妥協していました。

ルーティーン

ある日、郵便受けに地域の宅配屋を網羅した情報誌が入っていて、その中に、ルーティンというお店が紹介されていました。
このお店、宅配していない(テイクアウト)なのに、なぜか宅配屋の雑誌にのっていることに興味を引かれて試してみた所、大当たりでした。

個人でやっているお店で、ピザのサイズは25cm固定、種類は10種類程度なんですが、値段は全て1000円〜1500円程度の良心価格。
生地はうすいタイプで、もっちりしています(米粉を使ってるらしいです)。
チーズの味は、やや強め。
使用している具材も、保存料とか添加物とかも使ってないらしいです。
注文してから焼くので、10分〜15分程度は待つことになります(電話予約も可能)。

田舎の母に持ち帰った所、「今まで食べた中で、一番美味しい」と大好評でした。
もちろん私も大好評です。

サンプル

メニューに乗っている意外に、季節限定のピザを出しています。
これが、秋のピザです。
IMG_0742.jpg

秋だけあって、カボチャがのってたりします。
ちょっとカボチャの味が強い気もしますが、このあたりは個人の好みでしょうね。

ピザを頼むと、一緒にサラダを付けてくれました。
IMG_0743.jpg

後記

基本的にはテイクアウトなんですが、席(イートイン)もあります。
ピザ以外にも、総菜とかも扱っています(それも結構美味しい)。

場所は、北海道札幌市白石区菊水元町8条1丁目。
札幌の方でしたら、高速インターチェンジに向かう途中のTSUTAYAの向かいと行った方が分かりやすいかもしれないですね。

近くにお住まいの方は、ぜひ一度お試し下さい。

手作りピッツァ・お惣菜ルーティーン

昼総合点★★★★ 4.5



関連ランキング:デリカテッセン | 東札幌駅



--- blog end ---



スポンサードリンク

PageTop

NetCOBOLでSQLCAを使ってみる

SQLコミュニケーション領域(SQLCA)

SQLコミュニケーション領域(以下、SQLCAと記述)とは、SQLを実行した結果が格納される領域のことです。
SQLが実行されるたびにSQLCAの内容は書き換わります。

宣言

SQLCAは「 DATA DIVISION. 」 の 「 WORKING-STORAGE SECTION. 」 で記述します。
ホスト変数の宣言の直後か直前に記述します。


EXEC SQL BEGIN DECLARE SECTION END-EXEC.
*** ホスト変数の宣言 ***
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL INCLUDE SQLCA END-EXEC.


内部構造

SQLCAの内部は、プリコンパイラを通したソースから確認できます。
Ver.によって違いがあるようですが、私の環境ではこんな感じです。

【SQLCAの中身】

01 SQLCA GLOBAL.
05 SQLCAID PIC X(8).
05 SQLCABC PIC S9(9) COMPUTATIONAL.
05 SQLCODE PIC S9(9) COMPUTATIONAL.
05 SQLERRM.
49 SQLERRML PIC S9(4) COMPUTATIONAL.
49 SQLERRMC PIC X(70).
05 SQLERRP PIC X(8).
05 SQLERRD OCCURS 6 TIMES
PIC S9(9) COMPUTATIONAL.
05 SQLWARN.
10 SQLWARN0 PIC X(1).
10 SQLWARN1 PIC X(1).
10 SQLWARN2 PIC X(1).
10 SQLWARN3 PIC X(1).
10 SQLWARN4 PIC X(1).
10 SQLWARN5 PIC X(1).
10 SQLWARN6 PIC X(1).
10 SQLWARN7 PIC X(1).
05 SQLEXT PIC X(8).

【SQLCAの構造(一部)】

・SQLCODE - 最後に実行されたSQL文のステータスコードが格納される。

   0  ・・・ 正常

   >0 ・・・ 例外を検出。
         WHERE句の検索条件を満たす行がないか、SELECT INTOまたは
         FETCHで1行も戻されなかった場合。

   <0 ・・・ 致命的なエラーの発生

・SQLERRM

   SQLERRML ・・・ SQLERRMCに格納されているメッセージの長さ

   SQLERRMC ・・・ SQLCODEに格納されているエラーコードに対応
            するエラーメッセージ。

・SQLERRD(3)

   最後に実行されたSQL文で処理された行数。

なにで使うの?

NetCOBOLでは、ORACLE側でエラーが発生したとしても異常終了にはならず、処理が続行されます。
そこで、SQLCAのSQLCODEで直前のSQLの実行状態を確認したりします。

他には、UPDATE文を発行した時に、更新した件数を取得したい場合は、SQLERRD(3)を使用すれば件数を取得できます。

前回:NetCOBOLでのホスト変数の使い方
次回:NetCOBOLとOracleのデータ型の関係
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---


スポンサードリンク

PageTop

NetCOBOLでのホスト変数の使い方

ホスト変数とは

ホスト変数とはSQL文中に記述し、条件や値を受けとることが出来る変数のこと。
逆にいえば、ホスト変数以外はSQL文中に記述できません。

※ 前回(http://harikofu.blog.fc2.com/blog-entry-45.html)と内容が重複します。

ホスト変数の宣言

【構文】

EXEC SQL BEGIN DECLARE SECTION END-EXEC.

ホスト変数


EXEC SQL END DECLARE SECTION END-EXEC.


1.「 DATA DIVISION. 」 の 「 WORKING-STORAGE SECTION. 」 で記述します。
2.EXEC SQL BEGIN DECLARE SECTION END-EXEC.とEXEC SQL END DECLARE SECTION END-EXEC.で囲まれた範囲に宣言された変数がホスト変数となります。

宣言の例


EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 H-FSMACTTHTM PIC X(006).
01 H-CSVPUT-CNT PIC 9(012).
EXEC SQL INCLUDE XXXXX999.CBL END-EXEC.
EXEC SQL END DECLARE SECTION END-EXEC.


実際の宣言は上記の通り、注意点は 「 INCLUDE XXXXX999.CBL 」です。
INCLUDE文はCOBOL言語のCOPY句に該当します。
SQL文やホスト変数の宣言の場合はCOPY句ではなく、INCLUDE文を使用して下さい。

使用方法

実際のプログラム中では下記のように使用します。

【使用例】ABCDテーブルからFSASが10の件数を取得する

MOVE "10" TO H-FSMACTTHTM.
EXEC SQL
SELECT COUNT(*) INTO :H-CSVPUT-CNT
FROM ABCD
WHERE FSAS = RTRIM(:H-FSMACTTHTM)
END-EXEC.


上記の例のように、ホスト変数は EXEC SQL ~ END-EXEC の範囲内で使用するときは先頭に:をつける必要があります。

前回:NetCOBOLでOracleに接続してみた
次回:NetCOBOLでSQLCAを使ってみる
投稿記事の一覧 : http://harikofu.blog.fc2.com/blog-entry-22.html

--- blog end ---



スポンサードリンク

PageTop

ホワイトニングとやらをやってみたが...

あれからどうなった?

前回から、実は3回通院しています。
翌日と一週間後に状態のチェックってことで2回。
とりあえず、事件はおこらず傷口は順調に治ってきました。

その2回めの時に、「次はホワイトニングをしましょう」とか言われた。
...別に、そんなの頼んでないんだけどね。
まぁ良いでしょう。ちょっと興味もありますしね。

ホワイトニング

ホワイトニングってようするに歯ブラシでとれない汚れを取るってことらしいんですけど、具体的にはどうするんだろうって思っていたら、看護師さんがなんか高速回転するブラシのようなもの(詳細はわからん)で歯を磨き始めた。これが微妙に染みる。ぶっちゃけると、前回の差し歯を抜いた時より不快だったりする。
もしかすると、磨いてるんじゃなくて、削ってるんじゃないだろうか?

結果の比較

これが、実施前。
IMG_0738.jpg

これが実施後。
IMG_0740.jpg

正直、変わったようには見えないですね。
鏡でよくよく見てみると、なんとなく奇麗になったように見えるんですけど、凄く奇麗になったって感じじゃないですね。

衝撃の支払いと次回

終わった後に先生がやってきて、上の奥歯(両方)に小さな虫歯があるということで、見せてもらった。
ふむ、たしかに黒くなっている。
内訳は、左上で2本(1本は親知らず)、右上で1本の計3本ですね。

次回は、左上の治療をするそうです。
これも、別に頼んじゃいない(最初の問診票にも、差し歯の治療だけで良いと書いている)んだけど、せっかくの機会だし、直す事にしましょうかね。

そして、清算すると、なんと、1,700円!(保険もあるから、実際には5.000円超)。
差し歯を抜いた時と同じか、高くね?
こんなことなら、ホワイトニングなんてしなくてよかったんだけどなぁ。

スポンサードリンク

PageTop

NetCOBOLでOracleに接続してみた

NetCOBOLでOracle接続

使用するのはNetCOBOL
こいつ、Oracleとの接続は、結局Pro*COBOLだったりするようです。
最初、この関係が分らなくてWEBから資料を探すのが大変だった...

こうなった

試行錯誤のすえ、こんな感じになりました。
Oracleに接続して、何もせずに終了する処理です。

WORKING-STORAGE SECTION.
*
* 埋込みSQL宣言節の開始
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
*
* ORACLE接続コネクト用変数
01 USERNAME PIC X(016) VARYING. *> ユーザーID
01 PASSWD PIC X(016) VARYING. *> パスワード
01 DBSTRING PIC X(016) VARYING. *> 接続データベース

* 埋込みSQL宣言節の終了
EXEC SQL END DECLARE SECTION END-EXEC.
*
* オラクル共通
EXEC SQL INCLUDE SQLCA END-EXEC.
*
PROCEDURE DIVISION.
*
* *> 接続情報を設定
COMPUTE USERNAME-LEN = FUNCTION
STORED-CHAR-LENGTH("<ユーザ名>").
MOVE EV-WK-USERNAME TO USERNAME-ARR.
COMPUTE PASSWD-LEN = FUNCTION
STORED-CHAR-LENGTH("<パスワード>").
MOVE EV-WK-PASSWORD TO PASSWD-ARR.
COMPUTE DBSTRING-LEN = FUNCTION
STORED-CHAR-LENGTH("<接続先>").
MOVE EV-WK-DBSTRING TO DBSTRING-ARR.
*
* *> コネクト処理
EXEC SQL
CONNECT :USERNAME IDENTIFIED BY :PASSWD
USING :DBSTRING
END-EXEC.
*
* *> コミット!
* EXEC SQL COMMIT END-EXEC.
*
* *> ロールバック!
EXEC SQL ROLLBACK END-EXEC.
*
EXIT PROGRAM.


解説1 EXEC SQL ~ END-EXEC

そもそも、COBOLにはDBとやり取りするって機能が無いので、COBOL内に無理やりOracleとやり取りする部分を埋め込みます。
そのやり取りする部分ってのが、「EXEC SQL」から「END-EXEC」までの間になります。
なので、この範囲内の記述については、COBOL自体の書式とはかけ離れた記述方法になります。

解説2 ホスト変数

ホスト変数とはSQL文中に記述し、条件や値を受けとることが出来る変数のことです。
逆にいえば、ホスト変数以外はSQL文中に記述できません。


EXEC SQL BEGIN DECLARE SECTION END-EXEC.

ホスト変数

EXEC SQL END DECLARE SECTION END-EXEC.


「 DATA DIVISION. 」 の 「 WORKING-STORAGE SECTION. 」に記述します。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.とEXEC SQL END DECLARE SECTION END-EXEC.で囲まれた範囲に宣言された変数がホスト変数となります。

解説3 VARYING

ホスト変数のVARYINGってのは、可変長文字列ということです。
COBOLには固定長文字列(Xタイプ)しかないですが、Oracleには可変長文字列があります。
VARYINGと定義することで、COBOL側で可変長文字列に相当する受け皿(VARCHAR擬似型っていうらしいです)を作成できます。

この変数はプリコンパイラを通すと、下記のように2つの変数に分解されます。

01 USERNAME.
02 USERNAME-LEN PIC S9(8) COMP-5.
02 USERNAME-ARR PIC X(16).


まぁ、ここまでくれば分ると思いますが、***-LENには長さが、***-ARRには値が入ります。
サンプルでは、ユーザ名、パスワード、接続先のそれぞれで値と長さ設定しています。

長さの設定は、STORED-CHAR-LENGTH関数を使用します。
(NetCOBOLの専用関数で、実際の長さを返却します)

解説4 接続!

接続は、こんな感じです。

EXEC SQL
CONNECT :USERNAME IDENTIFIED BY :PASSWD
USING :DBSTRING
END-EXEC.


ホスト変数として定義した3つの変数を設定して接続します。
ホスト変数を使用する時は、変数の前に:(コロン)を付けて下さい。

解説5 セッション制御

コミットかロールバックを記述します。
上記のサンプルでは、あえてコミットをコメント化してロールバックだけ実行しています。

*> コミット!
EXEC SQL COMMIT END-EXEC.


*> ロールバック!
EXEC SQL ROLLBACK END-EXEC.


コミットもロールバックも指定しないでプログラムを終了した場合は、自動的にロールバックが実行されます。
なので省略しても良いのですが、普通はちゃんと書くでしょうね。
まぁ、一種のマナーみたいなものでしょうか。

ちなみに、セッション制御だけなので、Oracleからの切断はされません。

解説6 切断

上記のサンプルには書きませんでしたが、切断する方法は2つあります。
一つは、セッション制御文を使用する方法です。

*> コミット!
EXEC SQL COMMIT WORK RELEASE END-EXEC.


*> ロールバック!
EXEC SQL ROLLBACK WORK RELEASE END-EXEC.

「WORK RELEASE」の記述を追加しました。
これで、セッション制御文の発行と同時にOracleから切断されます。

もう一つの方法が、DISCONNECT文を使用する方法です。
...が、実際にはわざわざ使用する理由がないので試したことがありません。
なので、ここでも書けませんね。

ぶつぶつ独り言

私の会社の基幹システムって、バッチ処理はCOBOLだったりします。
オープン系でオンライン処理はJavaで、バッチ処理のみCOBOLなのですよ。

とはいえ、昔のホストコンピュータがあった時代みたいに、芸術的な(つまり読めない)ロジックを実装するんでなく、SQLを実行するための基盤みたいな使い方なんですよね。
なんか、なおさらCOBOLでなくてもいいような気がするんだけどなぁ。

ここまで愚痴っといてなんですが、別にCOBOLが嫌いなわけじゃないです。
固定長のテキストファイルを扱うのなら、この言語が一番便利じゃないです?

次回:NetCOBOLでのホスト変数の使い方
投稿記事の一覧:目次



スポンサードリンク

PageTop

クロスバイクでお尻が痛いのでなんとかしてみた

痛い痛い、お尻が痛い

出だしからなんですが、クロスバイクに乗ってるとお尻が痛い。
平坦な道を走っている時はそうでもないんですけど、段差の多い道を使ってると、だんだん痛くなってくる。
この手の自転車のサドルって何で固いんだろ?
軽量化とか理由があるんだろうけど、自分のように速度を重視しない人間にとっては、ただ痛いだけ。

インナーパンツ

という訳で、近所のイオンで自転車用のパンツを購入しました。
IMG_0717.jpg
※ ゴールドウイン(GOLDWIN) インナーパンツ GWB-925

パットが入っているので、痛みを軽減することが出来るようです。
んで、数回使ったんですけど、確かに効果はあるんだけど、長距離(20km以上)走ってるとやっぱり痛くなってきた。

サドルパッド

このあたりで「もしかして自分の姿勢が悪のでは?」とも思ったのですが、それを無視してさらに新アイテムを調達しました。

IMG_0709.jpg
※ サーファス [SERFAS] ハイブリッドサドルパッド

サドルにかぶせるタイプのパッドですね。
ちょっと固めのプニプニ感で、お尻を縦に割るように溝があります。
使い方は単純に上から被せて、紐でキュッと締めるだけなので、取り外しも簡単です。

試してみると、効果はあるのは分かるんですが、まだ痛い。
それに、微妙にずれたりするんですよね。まぁ、取り外しが簡単ってことは、ずれやすいってことでもあるので、しょうがないんですけどね。

結局

とりあえず、インナーパンツとサドルパッドの両方を合わせて使ってみます。
まだ試験段階なんですけど、今の所は好調です。

このまま痛くならないといいなぁ。

スポンサードリンク

PageTop

Excelのフィルタで空白行を抽出してみた

フィルタ

社内のユーザーから、フィルタ(オートじゃない方)の使い方で「何も入力されていない行を選択したい」と聞かれて即答できなかったので、いろいろ試してみました。

基本情報

Excel2010だと、フィルタは「データ」-「詳細設定」から選択します。
ExcelFilterフィルタ設定

テスト用の表を、こんな感じで作ります。
こいつで、いろいろフィルタを試して見ます。
ExcelFilter表

普通の使い方は、Excelのヘルプに詳しくのってるので、ちょっと変わったことをしてみます。

文字列が空白のデータ

「文字列」列が空白の行を抽出してみます。

検索条件には = とだけ入力します。
ExcelFilter文字列空白

ふむ、ちゃんと空白行だけ抽出できましたね。
ExcelFilter文字列空白結果

他の機能だと、空白選択って、="" じゃないですか。
なんか、ここだけ = ってのも違和感ありますよね。
統一してくれたら良かったのになぁ。

フィルタを解除

フィルタの解除は、「クリア」を押せば解除できます。
ExcelFilter解除

文字列が空白ではないデータ

次は「文字列」列が空白ではない行を抽出してみます。

こんどの条件は、 <> だけです。
ExcelFilter文字列空白外

うん、成功ですね。
ExcelFilter文字列空白外結果

計算式を利用したデータ抽出

Excelのヘルプを見て見ると、計算式も使えるようなので試してみます。

検索条件に、新しい列「条件」を追加して、計算式に表の先頭行の「文字列」列に対する関数「=IF(D3="",TRUE,FALSE)」を仕込みます。
ExcelFilter計算式

結果はこのとおり、関数の結果が空白になる行だけ抽出できました。
ExcelFilter文字列空白結果

どうやら、関数で設定した「D3」を自動的に各行に対する条件として判断してくれるようですね。
そして、結果が真(True)になる行だけを抽出するってもののようです。

とはいえ、これだけだと怪しいので、今度は値が入力されている行を抽出してみます。
やってることは同じですが、関数を「=IF(D3<>"",TRUE,FALSE)」に書き換えています。
ExcelFilter計算式2

結果は、「文字列」列に値が設定されている(関数の結果が真)行だけが抽出できました。
ExcelFilter文字列空白外結果

...計算式を使った条件設定は、一見便利に感じるけど正直使いたくないかな。
上手く言えないけど、感覚的にトラブルの原因になりそうな気がするんだよね。

最後に

しかし、フィルタなんて使ったのは10年以上前に学校で習って以来ですよ。
これ、便利なんだけど実務レベルだと、なかなか使う機会がないからすっかり忘れてました。
まぁ、勉強し直しのいい機会でしたね。

スポンサードリンク

PageTop

Excel2007&Excel2010のヘルプの表示方法

ヘルプはどこにいった?

マクロ(VBA)を作ってる時に、Excel2000の頃は調べたい文字を選択して、F1キーを押すとヘルプ画面が表示されて便利だったんだけど、Excel2007、Excel2010になってからは、この方法が使えなくなった。

いや、ヘルプ画面は表示されるんだけど、なぜかOffice.comとかを検索しに行きやがる。
そして、「該当結果はありません」とか言いやがる。

...うーん。

もしかしてこれか?

偶然の操作だったんですけど、ヘルプ画面の検索ボタンの右にある▼(下向き三角)を押すと、ヘルプの選択メニューが表示されました。

ん?もしかしてそういう事か?
とりあえず、このコンピュータ上のコンテンツから「Excel Help」を選択します。
WS001009.jpg

なんか、それらしい画面が表示されました。
この状態で、VBA上の「Msgbox」を選択状態にしてF1キーを押下します。
WS001010.jpg

おぉ、求めてたものが出てきましたよ!
そうです、これが欲しかったんですよ。
WS001011.jpg

愚痴

それにしても、ずいぶん不親切になった気がしますね。
別に回顧趣味があるわけじゃないですけど、これなら以前の方が使いやすかった気がします。
別にデフォルトでOffice.comを検索しに行くのは良いんだけど、それならちゃんと情報を表示して欲しいものですよね。それが出来ないなら、最初からローカルのヘルプを表示した方が良いと思うのだが...

私が未熟なせいなのか、Microsoftのいつものアレなのか知りませんけどね。
まぁ、今回は解決してよかったですよ。


スポンサードリンク

PageTop

Excel関数で引数を省略できる関数を使ってみる

Excelの関数は、引数の前にOptionalを付ければ、その引数を省略可能にすることが出来ます。
例えば、こんな感じですね。

'関数「test」
Function test(Optional ByRef pFlag) As Boolean
If CStr(pFlag) = "1" Then
MsgBox "1"
Else
MsgBox "2"
End If
End Function

'関数「test」を実行する処理
Sub aaa()
'関数「test」を引数を省略して実行
test
'関数「test」に引数を設定して実行
test("1")
End Sub


この時に、関数「test」側でpFlagが省略されたのか、設定されたのか判断したいことがあります。
そんな時には、IsMissing関数を使用します。
この関数は、引数が設定されなかった場合にTrueを返します。

使い方は、こんな感じ。

Function test(Optional ByRef pFlag) As Boolean
If IsMissing(pFlag) Then
MsgBox "省略されました"
Else
MsgBox "設定されました"
End If
End Function


ただし、この関数はVariant型での判定しか出来ません。
Excelのヘルプによると「引数が指定されたかどうかを判断するためのフラグが提供できないためです」と書いてる。
実際に、他の型で省略可能の引数を使ってみると...

'引数省略のテスト関数
Function test(Optional ByRef pStr As String, Optional ByRef pInt As Integer) As Boolean
MsgBox "[" & pStr & "] / [" & pInt & "]"
End Function

'引数省略関数「test」を実行する処理
Sub aaa()
test
End Sub

これで、aaaを実行するとこうなります。
WS001008.jpg

String型の場合は空白、Integer型の場合は0になります。
ようするに初期値ですよね。

なので、これらの型で引数省略の判定をしたい場合は、こうします。

'引数省略の確認関数
Function test(Optional ByRef pStr As String = "A", Optional ByRef pInt As Integer = -32768) As Boolean
If pStr = "A" Then
MsgBox "引数「pStr」が省略されました。"
End If
If pInt = -32768 Then
MsgBox "引数「pInt」が省略されました。"
End If
End Function


関数側で、呼出側で設定されない値を初期値として設定しておいて、もし初期値のままだったら省略されたものとみなすようにします。

※ 書いておいてなんですが、完全性に欠けるので個人的には好きじゃないです。
  なので、実際にはこういう使い方をしたことは無いです。

スポンサードリンク

PageTop

クロスバイクのチェーン磨いてみた

札幌は白石サイクリングロードを走ってきました。
片道17キロ位なので、気軽に行けるのが良いですね。

んで、帰ってきてチェーンを見てみると、大分汚れが酷くなってます。
IMG_0710.jpg

うーん。買ってからの状態は、距離にして100キロちょっと(江別の往復に、今日のお出かけ、他に毎朝1時間くらい走ってるからそんなもんでしょ)、購入してから半月程度でこれですか。

放っといても良いんですけど、秀岳荘(アウトドア専門店:http://www.shugakuso.com/)でこんなものを見つけました。
IMG_0718.jpg

チェーン専用の布ですか。こんなのもあるんですね。
まぁ、他にもチェーン専用のブラシとかも売ってたんですけど、家にモノを増やしたくないんで消耗品のこれにします。

んで、説明書き見てるんですが、拭くとしか書いてない。
とりあえず、布を左手に持ちチェーンを握り、その状態で右手でペダルをグルグルっと回転させてみました。
おぉ、なんかいい感じで汚れが落ちる。とか思ってたら、なんかガコッと不吉な音がしてチェーンが動かなくなりました。...いや、チェーン外れただけなんですけどね。

若干焦りつつ、チェーンの復旧を開始。
手こずるかと思ったんですけど、案外簡単にはまりました。ママチャリでチェーンはずれた時は、結構苦戦するんですけど、流石ですね。

とりあえず、方針転換。
右手でペダルを固定して、左手で布をもって見えている部分のチェーンをフキフキ。
拭き終わったらペダルを少し回して、またフキフキ。
どうやら、これが正解らしいです。まぁ、ちょっと考えたら当たり前なんですけどね。

結果はこんな感じ。
うむ、ピカピカですね。
IMG_0712.jpg

ちなみに、使用した布は2枚。
5枚入りなので、このペースだと一月ちょいで1セット使う事になるかな?
1セット200円〜300円位なので、邪魔で他に使い道のない専用ブラシ買うより良いですね。

...ちなみに、チェーンが外れたせいか、漕ぐとカリカリ異音がするようになった。
一度、メンテナンスしてもらった方がいいかなぁ。

スポンサードリンク

PageTop

大福堂の饅頭、ぜんざい、あんみつ

大福堂にまた行ってきました。
前回はこちら:大福堂でわらび餅とchocoわらびを食べてみた

今回は、饅頭、白玉ぜんざい、あんみつです。

饅頭

最もシンプルなこしあんの大福です。
IMG_0684.jpg
割ってみた。
IMG_0685.jpg

粒あんより、こしあんの方が好きなんですよね。
というか、餅が好きなんで、あんは味付け程度に入っていれば良いんです。
その点で行くと、ここの餅はモッチリしていて美味しいです。
ちなみに、そこらのスーパーで売ってる物とは違うので、翌日になると餅が堅くなります。

次も饅頭ですが、チョコレート饅頭とかって書いてたかな?
(もしかしたら、コーヒー饅頭かもしれん)
IMG_0686.jpg
同じく割ってみます。
IMG_0687.jpg

こちらのは、粒あんですね。
粒がはっきり分かるあんなので、粒あんが好きな方にはおすすめです。
生地にもチョコだかコーヒーだかの味がしみ込んでいて、これはこれでありかと。


白玉ぜんざい

白玉ぜんざいです。
IMG_0689.jpg
蓋を開けると、こんなかんじ。
IMG_0690.jpg

白玉は美味しいんですけど、その下が全部粒あんなんですよね。
粒あんはあんまり好きじゃないので、正直いまひとつ。
例えば、粒あんの中に小さく砕いた白玉を混ぜるとかってどうなんだろ?
あんのくどさが無くなって、食べやすくなるのでは?
...まぁ、素人考えかな。

あんみつ

最後にあんみつです。
IMG_0691.jpg

蓋をあけてみます。
IMG_0692.jpg

添付の黒蜜を掛けます。
IMG_0693.jpg

んで、感想。
「黒蜜いらなくね?」
見た目も悪くなるし、そもそも掛けなくても美味しい。
前回のわらび餅みたいに、別売りにすれば良いのに。

統括

結局、普通の饅頭が一番美味しかった。
まぁ、原因は自分があんがあまり好きじゃないってだけで、あんが好きな人には違う意見がありそう。

実は、これら全て日本酒のおつまみにしました。
なにげに、日本酒って甘いお菓子ともあうんだよね。

スポンサードリンク

PageTop

自転車(クロスバイク)で音楽聞きたい

イヤフォンは危ない

クロスバイクで走ってみて(クロスバイクの試運転(江別河川防災センター)分かった事の一つに、イヤフォンで音楽を聴くのは危険すぎるってことです。
ママチャリ使ってる時は、あまり気にしなかったんだけど、クロスバイクの速度で音が聞こえないのは怖すぎる。
条例とかで禁止されるのがよくわかるよ。

だけど...

それでも、音楽は聞きたいんだよね。お気に入りの音楽聞きながら、河川敷をのんびり走るって最高じゃね?
イヤフォンは危ないけど、スピーカーならいけるかなと思い、とりあえずググって調べてみると、自転車用の音楽プレイヤーがたくさん見つかった。同じ事を考える人って多いみたい。
問題なのは、

「今持っている音楽プレイヤーで聞きたい」

ってことなんだよね。
iPodとかiphone用のは見つかったんだけど、自分のはSONYのウォークマンだったりする。

秘策あり

そんな時に、こんな商品を見つけました。
IMG_0635.jpg
※スマホ対応自転車用フレームポーチ:http://www.thanko.jp/index.html

中は、こんな感じ。
本来は、写真で人差し指を突っ込んでいる所にスマホを入れる商品です。
IMG_0636.jpg

これだけでは、意味がないんですけど、こういう物を持っているのです。
IMG_0644.jpg
※ピタッとスピーカー:http://www.devicenet.co.jp/pita/

音楽プレイヤーと繋いで、いろんなモノにくっつけることでスピーカにする面白商品です。
自分はこれを風呂の戸に付けて、入浴中に音楽を楽しんでます。

んで、ウォークマンはこれです。
IMG_0642.jpg

スマホを入れる部分に、ウォークマンを入れて、ピタッとスピーカーとこんな感じで繋ぎます。
IMG_0646.jpg

吸盤部分を外に出した状態で、チャックを閉じます。
IMG_0647.jpg

装着!

吸盤は自転車にくっつけます(吸盤を水で湿らせるとくっつきやすいです)。
IMG_0654.jpg

再生してみると、ちゃんと音楽は聞こえます。
ただ、音量とか音質は今ひとつですね。
自分は、聞こえれば良いタイプなので気にしませんが、音質云々言う人は、小細工せずに専用商品を使った方がいいでしょうね。

問題は、ピタッとスピーカー、ちょっと大きいことですね。
できれば、このポーチの中に財布、鍵、デジカメも入れたいけど、現状では入らない。
後で調べると、ミニサイズも売ってるらしいので、そちらの方が良いでしょうね。

スポンサードリンク

PageTop

powerShellをoperationManagerから実行してみた

ジョブの作成

powerShellをoperationManagerで実行してみます。
Windowsのタスクでも出来るんですけど、せっかくジョブを実行できるソフトがあるので、こちらを使います。

実行するスクリプトはこれ。

D:\script\pingChk.ps1


実際の設定は、こんな感じ。
operetionManagerとpowerShell

環境によっては、コマンドの「v1.0」の部分が変わるんでしょうかね。
Ver.上げる気が無いので、確認できませんけどね。

他のタグの設定は、初期値のままにします。

スクリプト

「pingChk.ps1」の内容です。
ロジック部分は長いので省略してます。やってることはpingとかなんで、別の記事(下段リンク「目次」)からご覧ください。

# フォルダ構成を定義
[System.String]$RootDIR = 'D:\script'
[System.String]$LogDIR = $RootDIR + '\log' # ログ

# 処理開始時点での日時情報
[System.String]$OpeDate = Get-Date -format yyyyMMdd_HHmmss

# ログファイル定義
[System.String]$LogName = $LogDIR + '\' + $OpeDate + '.log'
[boolean]$LogDateTrue = 1 # ログ出力関数用 「日時を追加する」
[boolean]$LogDateFalse = 0 # ログ出力関数用 「日時を追加しない」

# ----------------------
# ログ出力用関数
# ----------------------
# 【機能概要】
# メッセージを、画面とテキストファイルに追加書込みします。
# 出力時に日時を追加表示することも可能です。
# 【引数】
# msg 表示するメッセージ
# file 出力するテキストファイルの完全パス
# dspTimeFlag メッセージへの日時に追加出力(0:追加しない, 1:追加する)

function msgOutput([String]$msg, [String]$file, [boolean]$dspTimeFlag) {
if ($dspTimeFlag) {
$WkLogTimeMsg = Get-Date -format yyyy/MM/dd-HH:mm:ss
Write-Host ($msg + ' : ' + $WkLogTimeMsg)
Write-Output ($msg + ' : ' + $WkLogTimeMsg) | out-file $file Default -append
} else {
Write-Host $msg
Write-Output $msg | out-file $file Default -append
}
}

# ----------------------
# エラートラップ関数
# ----------------------
# 【機能概要】
# 各スクリプトのtrapで実行するエラー共通処理です。
# ログと画面にエラー内容を出力します。

function errorTrap() {
msgOutput '' $LogName 0
msgOutput '□□□□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
msgOutput '□' $LogName $LogDateFalse
msgOutput '□ 異常終了しました。' $LogName $LogDateFalse
msgOutput '□' $LogName $LogDateFalse
$Error[0] # ログ関数に渡すと、エラー発生個所とかが消えるので直接ログに
Write-Output $Error[0] | out-file $LogName Default -Append # 書込みを行います。画面にも表示したいので2行になります。
msgOutput '□' $LogName $LogDateFalse
msgOutput '□□□□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
}

# エラートラップを準備します。
trap {
errorTrap
exit 99
}

# 処理開始
msgOutput '□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
msgOutput '死活監視を開始します。' $LogName $LogDateTrue
msgOutput '□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
msgOutput '' $LogName $LogDateFalse

*** ロジック ***

# 正常終了
msgOutput '□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
msgOutput '死活監視を終了しました。' $LogName $LogDateTrue
msgOutput '□□□□□□□□□□□□□□□□□□□' $LogName $LogDateFalse
exit 0


スクリプトのエラーコードはexitの後に数値を入れることで設定できるようです。
なので、処理の先頭でエラートラップを仕込んで、異常時にはエラーコード「99」が返却されるようにします。
処理が最後まで実行された場合には「0」が返却されるようにします。

テスト

スクリプト自体は、事前に手動で動作を確認しておきます。
んで、さっそくoperationManagerから起動してみると見事に異常終了しました。

Windowsサーバーが64bit版で、operationManagerが32bit版である関係で、実行時ポリシーの設定を32bit用のpowerShellに対して設定しないといけなかったようです。

  詳細はこちらを参照 http://harikofu.blog.fc2.com/blog-entry-36.html

ポリシーを設定して再度実行すると、またまたエラーが出る。
なんだろ?

実験しましょう

発生条件を掴むために、いろいろと実験してみました。

test.ps1



# エラートラップの設定
# 全てのエラーを捉えたいので、ErrorActionPreferenceにstopを設定

$ErrorActionPreference = "Stop" # Stop(停止), Inquire ( 問い合わせ ), Continue ( 続行 )

Write-Host ('テスト開始')

& 'D:\script\testBat.bat'

Write-Host ('テスト終了')

# -----------------------------
# 正常終了
# -----------------------------

Write-Host ('正常終了')
exit 0

# ----------------------
# エラートラップ
# ----------------------

trap {
Write-Host ('異常終了')
$Error[0]
exit 99
}


testBat.bat



exit


単純に、powerShellからバッチを実行するだけの処理です。
実際に、これを実行した結果が下記のログです。

テスト開始
D:\script>exit
異常終了
Write-Host : OS ハンドルの位置が FileStream が予期していた位置ではありませんで
した。FileStream 内と Win32 コード内または別の FileStream 内で 1 つのハンドルを
同時に使用しないでください。データが失われる可能性があります。
発生場所 D:\script\test.ps1:10 文字:11
+ Write-Host <<<< ('テスト終了')
+ CategoryInfo : NotSpecified: (:) [Write-Host]、IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Comma
nds.WriteHostCommand


ふむ、どうやらpowerShellから別のジョブを実行するとエラーになるようです。
バッチファイルの他に、Oracleのエクスポートなども試して見ましたが、同じように異常終了します。
ちなみに、powerShellからpowerShellの実行は問題なく動作しました。

サポートセンターに聞いてみた

正直、お手上げです。
なので、サポートセンターに上記のスクリプトを送って原因を教えてもらうことにしました。

実行ポリシーの部分でも書きましたけど、サーバが64bit版でoperationManagerが32bit版の時に、こういう現象が発生するらしいです。
operationManagerが32bit版の場合、powerShellは32bit版で実行され、その結果、ジョブが正しく動作しないらしいです。
はっきりとは言ってませんでしたが、operationManagerは悪くなくて、Microsoft側の問題という感じの回答に聞こえました。

...なんか、納得し難いですね。
32bit用のpowerShellで手動実行しても正常終了するわけだし、operationManager側で対応できないものなんだろうか?
うーん、JP1だとどうなんだろうなぁ?

スケジュール登録

まぁ、特定条件下で動かないってのは、よくある話なので回避策をとる事にします。
やりようは、いくらでもありますしね。
今回は、外部バッチを実行していた部分をoperationManagerから直接実行させることにしました。

後は、実行スケジュールは、毎朝実行するように設定して完了です。

富士通SupportDesk

サポートセンターって書いてますけど、実際は「富士通SupportDesk」ですね。
数回使った感想としては、結構頼りになると感じてます。

今回は「もう少しなんとかならんか?」と思う回答ではありましたが、operationManagerって製品自体に回避策が無い以上、サポートデスクとしては、これ以上の回答は出来ないでしょうしね。


投稿記事の一覧:目次

スポンサードリンク

PageTop

powerShellの実行ポリシーを変更してみた

■ 実行ポリシーの変更

クライアント(WindowsXP)で作成したpowerShellをサーバにコピーして実行してみました。
すると、こんなエラーが発生しました。
スクリプトの実行がシステムで無効になっているため、ファイル D:\疎通確認\script\test.ps1 を読み込めま
せん。詳細については、「get-help about_signing」と入力してヘルプを参照してください。
発生場所 行:1 文字:42
+ D:\疎通確認\script\test.ps1 <<<<
+ CategoryInfo : NotSpecified: (:) []、PSSecurityException
+ FullyQualifiedErrorId : RuntimeException


どうやら、実行ポリシーとやらがあるようで、調べてみると4種類見つかりました。

Restricted : 全てNG。デフォルトはこれらしい。
AllSigned : 署名されてたらOK。
RemoteSigned : ローカルのはOK。ネット上のは署名されてたらOK。
Unrestricted : 全てOK。ただしネット上のは実行に確認が必要。

とりあえず、実行ポリシーを変更します。「RemoteSigned」はローカルは可、インターネットダウンロードは署名付きを許可。まぁ、これで良いでしょ。
Set-ExecutionPolicy RemoteSigned


Get-ExecutionPolicyで結果を確認できます。
Get-ExecutionPolicy


operationManagerから実行してみる

手動では実行できるようになったんですが、operationManager(富士通製のジョブ実行ソフト。JP1みたいなやつ)から実行すると、「スクリプトの実行が許可されていない」っつーエラーが出てきやがる。

これ、Windowsが64bit、operationManagerが32bitの時に発生するようです。
どうやら、powerShellは64bit用と32bit用の2種類用意されているらしく、普通にポリシーを変更すると64bitの方が変更されるようなのです。
なので、operationManagerから実行する場合は32bit用のpowerShellの実行ポリシーを変更する必要がある。

んで、それぞれの場所は以下の通り。
まぁ、バージョンによって場所違うだろうけどね。

64bit


C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

32bit


C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe


ssytem32がSysWOW64に変わっただけであとは同じ。
このあたりは64bit版WindowsOSが32bitアプリを動かす仕組みの話なので、気になるならWOW64(Windows 32bit emulation on Windows 64bit)あたりでググって下さい。

32bit版のpowershell.exeを起動して、実行ポリシーを「RemoteSigned」に変更すると、operationManagerで動作するようになりました。
やれやれです。

投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end ---


スポンサードリンク

PageTop

クロスバイクの試運転

出発進行!

いろいろ考えたんですけど、目的地を江別河川防災センターに定めます。
とにもかくにも、クロスバイクの感覚を体に覚え込ませる為に長距離を走ります。
私は札幌市白石区にいるので、往復で40km位になりますね。

天気はこんな感じ。結構曇ってますね。
IMG_0605.jpg

天気予報によると、降水確率50%で実際にパラパラと降ったり止んだりしていました。
ちょっと心配だったんですけど、しばらくすると晴天になったので無用の心配でしたね。

しばらく(信号とかで)乗降りを繰り返してると、乗る方はだいぶ慣れてきたんですけど、降りるときの感覚が今ひとつしっくりこないんですよね。
大丈夫かなぁって思いながら、ふと横の公園を見ていると...
IMG_0608.jpg

痛いです

案の定降りる時にバランスを崩して、降車に失敗。
ご覧の有様です。
IMG_0606.jpg

とりあえず、お出かけ用の治療セットで手当をします。
擦り傷だけで、骨とかに異常なさそうなので試運転は続行です。
IMG_0607.jpg

...一週間後、傷口を見てみると周囲が痣になっていて、内出血も確認。
思ったよりもダメージは深かったようです。

到着

さて、気を取り直してのんびりと漕いで行きます。
大きな川を超えて、はい!到着!
IMG_0613.jpg

まぁ、ここって特に変わった物がある訳じゃないんですよね(車で1度来ている)。
たしか、2階に食堂があったので、お昼ご飯を食べて帰る事にします。

これがメニューです。
うなぎ関係が全部「品切れ中」になってます。
今年はウナギが異常に高いので、それが原因かも知れないですね。
IMG_0614.jpg

ラーメン美味しいです

頼んだのは、メニューの端に手書きで書いている醤油ラーメン。
もちろん、こういう所で味を期待してはいけません。
IMG_0617.jpg

...と思ったんですけど、意外と美味しい。
チャーシューは半分がトロッと解ける食感で、私の好み。
そして、何よりも麺がぴったりでした。普通の麺に比べてもっちりとしていて美味しかったです。
店員さんに聞いてみると、道産小麦100%の麺だそうです。
もちろん、スープは業務用の既製品で全体としては高得点って訳じゃないですけど、値段が500円ということを考えると、全然悪くないです。

1階には土産物屋があるので、そこでラーメンを購入。
これ、インスタントラーメンじゃなくて、スープを別に作るタイプのやつです。
IMG_0688.jpg

後日の話ですが、お湯を電気湯沸かし器で湧かしながら、ラーメンをフライパンで茹でて食べました。
(フライパン?って思ったかもしれないですけど、これ、オススメですよ。なんと煮こぼれしないんです)
スープはともかく、麺はやはりもっちりしていて美味しかったです。

帰ります

さて、そろそろ帰りますか。
国道12号線沿いに札幌に戻ります。
すると、途中に自転車専用道が整備されていました。
IMG_0618.jpg

クロスバイク乗ってみて分かったんですけど、かなりスピード出るくせに、ママチャリに比べて緊急時のバランスが悪いように感じたんですよ。
もちろん、乗り馴れていないってこともあるんだとは思うんですけどね。
まぁ、つまり、非常に危ないんです。歩行者にぶつかったら、お互いに無事で済むとは思えません。
なので、こういう専用道があると、とても安心できますね。

では、本日はこれまでとします。

スポンサードリンク

PageTop

創成川公園サンキューフェスティバル

創成川公園サンキューフェスティバルに行ってきました!
先月くらいに広報札幌に載っていたので、暇があれば見に行こうと思ってたんですよ。
場所は創成川公園狸二条広場。
自転車に乗って、ゆっくり漕いで、はい到着。

IMG_0679.jpg

二条広場って初めてきたんだけど、結構小さい場所で、お店が十数店でてますね。
ぱっと見る限り、海産物を扱うお店が多いようです。
時間はちょうど昼頃なので、ここで昼食にする事にしました。

とりあえず、厚岸の焼き牡蠣が美味しそうだったので食べてみます。
盛況らしく、順番待ちの札を渡されて5分程まってから手に入れました。
IMG_0677.jpg

すごく美味しいです!
そして、ビールが欲しい!
でも、自転車で来てるから酒は飲めないんだよなぁ。

んで、気を取り直して次の店に向かいます。
今度は、ホタテとアワビです。これはすぐに買えました。
IMG_0678.jpg

うん、これも美味しいです!
なんか、テンション上がってきました!

さて、周りを見回すと、ツブが目に入りました。
これ、好物なのでぜひ食べたい。という訳で行ってみたんですが、なんか「焼いてる最中」とのこと。
その割には番号札とかくれる訳でもない。
まぁ、しばらく時間おきますか。

出店の最後列をみると、ノンアルコールビールを発見!
早速、買ってみました。ビールは白と黒があるらしいので、とりあえず白を買います。
ついでに、ラム肉の串焼きもゲットです。
IMG_0682.jpg

うんうん、これも美味しいですよ。
さて、大分お腹が膨れてきたので、最後にツブとビール(黒)で締めにしようと思います。
とりあえず、元気に演奏している若い子たちを眺めながら時間を潰します。
IMG_0683.jpg

そうこうしている内に、ツブが焼けてきたのか皿にとっているのが見えました。
では、行ってみましょう。

......ところが、焼いてるおばちゃんに声をかけると、こちらを見もせずに「先に待ってる人がいるいるから」とか言いやがる。
はぁ?俺も待ってるんだけど?
先にも書いた通り、別に番号札とか配ってる訳でもないのに、どういう順番なの?

とりあえず、場を離れて観察してみると、焼けたツブをとあるテーブルに持っていっておしゃべり開始。
ふーん、そういうこと。こんな堂々と友達ごっこするんだぁ。もういいよ。

急にどうでも良くなりました。
ステージじゃなんか演奏やってるけど、気持ちが冷めたので帰る事にします。
嫌なイメージが付いたので、二条広場に行く事はもうないでしょうね。


投稿記事の一覧:目次




スポンサードリンク

PageTop

クロスバイク買いました!

ママチャリの限界

しばらく前に、滝野すずらん丘陵公園にママチャリで行ったんですけど、上り坂のキツさにママチャリの限界を感じました。
しばらく悩んだ末に、よくヘルメットかぶった人が使ってるようなカゴのない自転車を購入する事にしました。
んで、ネットでいろいろ調べたんですけど、正直な話、自転車の種類がこんなにあるとは思ってませんでした。

正直な話、さっぱり分からなかったので自転車屋にいって聞いてみる事にしました。

自転車屋を探そう

というわけど、まずは自転車屋を探す事にします。
まぁ、どこにでもあるんですけど、個人でやってる店だと愛想がなかったりするので、数店舗巡って、話しやすい人がいるところを探しました。
選択基準はそれだけど、置いている商品の種類とか内容は二の次です。

結局、近所のイオン(札幌東苗穂店)に若い兄ちゃんが数人いたので、この人たちに声をかけて見ました。
要望は、「そこそこ走れて、通勤でも使えるやつ」って行ったら、クロスバイクを進められました。
なんでも、「ロードだとタイヤが細すぎてやり過ぎ、MTBだと逆にタイヤが太くて負担が大きい」とのこと。

無知な分野なので、とりあえず言いなりになっておきます。
言いなりついでに、必要そうな物(泥よけ、ライト、飲み物ホルダー)も一緒に買っておきます。
ちなみに、鍵は自分で持っていた物をそのまま使用することにしました。

購入!

全景です。
IMG_0599.jpg

ライト。道を照らすためじゃなく、自分の存在を知らせる為の物ですね。
つまり、夜はこの自転車は封印した方がよいでしょうね。
IMG_0600.jpg

ドリンクホルダーです。
単純にペットボトルだと温くなるのが課題ですね。
IMG_0601.jpg

最後に、泥よけです。見ての通り、未装着なんですけどね。
普段は取り外しておいて、雨のときだけ付ける事が出来るタイプです。
IMG_0602.jpg

初期指導

初めてのクロスバイクなので、ママチャリとの違いを教わりました。
曰く「乗降りする時は、重心を前に移すようにしてする」とか「切り替えは、こぎながら行う。」とかですね。
ママチャリしか知らんので、目から鱗が落ちる感じです。
乗ってみると、異様に前傾姿勢だし大丈夫なんだろうか?

とりあえず、試運転でどっか走ろうかな?

投稿記事の一覧:目次




スポンサードリンク

PageTop

歯ぐきの水ぶくれの治療が大事になりました No2

前回(前回の記事)の治療の続きです。

行ってみます


9時30分の予約なので、10分程早く着くように出発します。

歯医者さんの外観はこちら。
結構奇麗な建物ですね。
IMG_0659.jpg

今日は、歯を削ったり、差し歯を抜いたりします。
この差し歯、地元の歯医者さんで入れてもらった時は、洒落にならないほど痛かったので、今日は緊張でガチガチです。

削ります。抜きます。


予約のかいあって、直ぐに順番がきます(心の準備はまだなんだけどなぁ)。
まずは、麻酔ですよね。注射の前に、なにやら脱脂綿みたいなので歯ぐきを触られました。
どうやら、これも麻酔の一種のようで、下で触ってみるとちょっとしびれました。
これ、大人はともかく子供には良いかもしれないですね

んで、表と裏に数回ずつ注射して作業開始です。
まず、差し歯の左右の歯を土台に出来るように削ります。
うん、ギュインギュイン音立ててますけど、痛くないです。

そして、メインデッシュの差し歯の引き抜きです。
何度も書きますが、入れた時は「麻酔効いてるのか?」と疑う程の激痛で、20年近くたった今でも忘れられないトラウマだったりします(そのせいで、いい年して歯医者が怖い)。

そして、ついに先生の工具が差し歯を挟み......

グイッ!グイッ!

うがぁあああぁぁぁぁぁ?
あれ?痛くない
おぉ!痛くないぞ!素晴らしい。

しばらく作業してたんだけど、最後まで痛みはなし。
ありがたやありがたや。

この時、抜いた差し歯がこれ。
IMG_0669.jpg
てっきり差し歯って一体成形と思ってたんですけど、歯の部分と土台の部分で分離する用ですね。

仮歯を入れます

作業後、止血してから仮歯を入れます。
てっきり簡単に入ると思ったんですが、微調整が必要なようで看護師さんが何度も削って、噛み合わせを確認して、また削るを繰り返してくれました。
最終的には、噛み合わせバッチリの仮歯の完成です。

治療後の写真がこれです。
歯ぐきの部分が出血しているのが、差し歯だった部分ですね。
どうやら、歯ぐきを縦に切開したようです。
IMG_0667.jpg

諸注意とお薬

治療は、これで終了。
諸注意として、今日は運動ダメ、飲酒ダメ、お風呂ダメ。つまり汗かくことしちゃダメ。とダメのオンパレード。
うーん、できればサイクリングに行きたかったんだけど、まぁしょうがないよね。

後は、化膿止めと痛み止めをもらって本日は終了です。
IMG_0662.jpg

外科的な施術の後に、痛み止めをもらった事が数回あるんだけど、実は使った事ってなかったりするんだよね。
ブログ書いているいまも、患部は痛くないし、今回も使わずに済みそう。
まぁ、どうでも良い事か。

次回は...

次は、また一週間後と思ってたんですけど、「状態を見たいので、明日来て下さい」とか言われました。
....うーん、休日の予定が台無しですね。まぁ、恨むなら若い頃に虫歯になった自分なんですけどね。

それにしても、この1本のために、健康な左右の歯を犠牲にすることになったのは痛恨ですね。

スポンサードリンク

PageTop