"i5" の一覧

AS400のクエリで日付演算

AS400上のクエリで日付演算するには・・・

文字→日付

CAST(‘2009-05-07’ as DATE) as TEST

日付演算(DATEADD関数の代わり)

CAST(‘2009-05-07’ as DATE) – 7 DAY as TEST

 

前に調べたけど、忘れてしまいかなり探しました。区切り文字の’-‘はAS400のバージョンに依存するかもしれません。この表記はV5R4で確認。

AS400の異常をメールで通知する(3)

前回のように設定すると4つほど問題が発生。

1. 前回指定したコマンドが動かない

RUNRMTCMD CMD(’D:\CMDS\AS400MAIL 1.BAT’) RMTLOCNAME(’192.168.xxx.xxx’ *IP) CCSID(943)

これでエミュレータ上では正常に呼び出せていたが、iSeriesナビゲータを経由するせいなのか、「必要なユーザー ID がないかまたは無効です。」と言われる。結局、下記のように修正した。

RUNRMTCMD CMD(’D:\CMDS\AS400MAIL 1.BAT’) RMTLOCNAME(’192.168.xxx.xxx’ *IP) RMTUSER(TEST) RMTPWD(TEST) CCSID(943)

2. パスが認識されない

WS000063

困ったことに、iSeriesナビゲータ上のコマンド呼び出しでは¥(ほんとは半角)が使えない模様。

WS000054

物は試しということで、/(スラッシュ)にしたらOKだった。

RUNRMTCMD CMD(’D:/CMDS/AS400MAIL 1.BAT’) RMTLOCNAME(’192.168.xxx.xxx’ *IP) RMTUSER(TEST) RMTPWD(TEST) CCSID(943)

3.  CSCRIPTが応答メッセージを返す

BATファイルでいうところの@echo offをvbs呼び出し時に指定していなかったので、標準出力に下記のメッセージの大文字の箇所だけ出力されていた。

Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

よってAS400MAIL.BATを下記のように修正

cscript //B AS400Mail.vbs

4. RUNRMTCMDが邪魔する

ここまでの対応で晴れて標準出力(?)へ出力されるメッセージが無くなった。すると・・・

WS000065

というメッセージを親切に出してくれる。ググって出てきた結果、「OVRPRTF QYSPRTをHOLDしDLTSPLFして下さい。 」が理解できない・・・というか、影響範囲が解らずやっていいか判断できず。

今はメッセージモニタの実行ユーザーを別途作成し、そのユーザーが出力する先に仮想PRTデバイスを指定してます。が、すごく暫定的な対応で残念過ぎる。今回の手法はすごくお薦めできません(涙)

もし設定した人が居たらごめんなさい。

AS400の異常をメールで通知する(2)

前回の続きです。

iSeries Access for Windows リモート・コマンドの設定

WS000052 AS400Mail.vbsとAS400MAIL.BATを設置したサーバーにて「」サービスを起動します。
WS000057 再起動時にも開始されるように自動にします。
WS000058 デスクトップとの「対話サービスの許可」が無くてもOKでした。
WS000060 空白などが含まれないパスにAS400Mail.vbsとAS400MAIL.batをコピーします。
ここでは「D:\cmds」としました。

iSeries Access for Windows リモート・コマンドの設定

WS000051
WS000053
WS000054 監視するメッセー ジ対象とRUNRMTCMDを指定。

RUNRMTCMD CMD(‘D:\CMDS\AS400MAIL 1.BAT’) RMTLOCNAME(‘192.168.xxx.xxx’ *IP) CCSID(943)

これでいけました。

WS000050 メッセージ監視間隔を指定。
WS000055 この辺は特に触ってません。
WS000061 AS400のIPL時にメッセージのモニタが停止してしまう場合は、この辺をチェックすると治る。
RUNRMTCMD CMD(‘D:\CMDS\AS400MAIL.BAT’) RMTLOCNAME(‘192.168.xxx.xxx’ *IP) CCSID(943)

上の’D:\CMDS\AS400MAIL.BAT’部分を

RUNRMTCMD CMD(‘D:\CMDS\AS400MAIL.BAT 1’) RMTLOCNAME(‘192.168.xxx.xxx’ *IP) CCSID(943)

などにするとAS400Mail.vbsのCASE文のメッセージでメールが送信されます。

ちなみにメッセージをモニタする方法はiSeriesナビゲーターでしか無いらしい。あと、AS400MAIL.BATに@ECHO OFFを設定しないと標準出力のプリンタからなんか出てきます。

以上がAS400をDBとしてしか使えない人によるAS400の監視方法でした。また、より良い方法を求めています。コメント募集中です。

2009/04/26追記

この設定のままでは、正常に動作しない箇所があったので後日続編を書きます。

AS400の異常をメールで通知する(1)

AS400の異常をメールで通知する方法を探していたが、

外部のSMTPサーバーを利用してメールを送信する事はできない。
SMTPサーバーを立てても日本語は扱えない。
SMTPサーバーを立ててもユーザーが無いと送信できない

などの諸事情と自身のAS400に対するスキルの無さを踏まえた上で下記の方法を取った。

AS400自身からメールを送信することは諦めて、RUNRMTCMDを使う

こうしてしまえばあとはWindowsの領域に無理矢理引きずり出せる。VBScriptは起動時に

cscript AS400Mail.vbs

としなくてはならないので、呼び出し用のbatファイルを組み合わせました。メールのSubjectとBodyをvbs内で設定するようにしたのは、batファイルから渡せなかった為の妥協です(汗)。

AS400Mail.vbs

Set a = CreateObject("CDO.Message")
a.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
a.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "192.168.xxx.xxx"
a.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
a.Configuration.Fields.Update

a.From = "xxxx@exsample.com"
a.To = "test@exsample.com"
a.Subject = "[AS400]エラー通知"
a.TextBody = "AS400にてエラーしました。" & vbCrLf

'// 送信パターン指定があるか?
If WScript.Arguments.Named.Exists("I") Then
    iSendMode = 0

    If WScript.Arguments.Named("I") <> "" Then
        iSendMode = CInt(WScript.Arguments.Named("I"))
    End If	

    SELECT CASE iSendMode
    CASE "1"
        ' 01 ファイルロックモニタ用
        a.Subject = "[AS400]ファイルロック発生通知"
        a.TextBody = "AS400にてファイルロック発生通知が発生したようです。" & vbCrLf
    CASE ELSE
        a.Subject = "[AS400]エラー通知"
        a.TextBody = "AS400にてエラーしました。" & vbCrLf
    END SELECT
End If

'// 時刻を末尾に追加
a.TextBody = a.TextBody & Now

'// メール送信
a.Send

AS400MAIL.BAT

cscript D:\cmds\As400Mail.vbs /I:%1

i5(AS400)でCURRENT_TIMEの区切り文字

SELECT
    CURRENT_DATE,
    CURRENT_TIME
FROM
    TESTLIB.TEST

こんなSQLを流してみると、ODBCとiSeries Access for Windowsで時刻の区切り文字が違う事を発見。日付を数値で格納しているカラムへ現在の日時を保存するためのクエリが接続方式によって若干変わります。

現在時刻→数値(hhmmss)

ODBC

CAST(REPLACE(CAST(CURRENT_TIME AS VARCHAR(10)), ‘:’ , ”) as INTEGER)

iSeries Access for Windows

CAST(REPLACE(CAST(CURRENT_TIME AS VARCHAR(10)), ‘.’ , ”) as INTEGER)

iSeries Access for Windowsでの確認はC:\Program Files\IBM\Client Access\Shared\cwbundbs.exeを使いました。※iSeries Access for Windowsインストール後に*.sqlに関連付けされていたのをプロセス名から辿って探したけどアプリ名は何なんだろう・・・

i5(AS400)の特殊文字を含むカラム名の取扱い

i5(AS400)に対してODBC経由でSELECTはもちろん、INSERT,UPDATEなどのクエリも問題なく処理できるのですがプログラムのインストールとは別にIBM iSeries Access for WindowsをインストールしODBCの接続設定をしないと動作しません。しかもODBCの接続設定名も間違っていてはいけません。

そのためiSeries Access for Windowsに含まれるIBM.Data.DB2.iSeries(.Netプログラミングサポート時にインストールされる)を利用してクエリを実行するにはどうすればよいか悩んでました。

というのも、@@TESTというカラムが存在していた場合にODBCなら[@@TEST]と記述すれば問題なかったが、iSeries Access for Windowsで同じように記述するとエラーとなる。

結局、"(ダブルクォテーション)を使えばうまく行くことがわかった。実際には"@@TEST"となる。"(ダブルクォテーション)はC#上でも特殊文字なので記述が面倒だけど。

public void UpdateTest(string sValue)
{
    const string CRLF = @"\r\n";
    StringBuilder sbSql = new StringBuilder();

    sbSql.Append("UPDATE" + CRLF);
    sbSql.Append("    TESTLIB.TEST0407" + CRLF);
    sbSql.Append("SET" + CRLF);
    sbSql.Append("    \"@@TEST2\" = @TEST2" + CRLF);
    sbSql.Append("WHERE" + CRLF);
    sbSql.Append("    \"@@TEST1\"= @TEST1" + CRLF);

    try
    {
        using (iDB2Connection cn = new iDB2Connection(DataSource=192.168.xxx.xxx;USERID=(ユーザー名);PASSWORD=(パスワード);))
        {
            cn.Open();
            using (iDB2Command cmd = cn.CreateCommand())
            {
                sbSql = sbSql.Replace(CRLF, " ");
                cmd.CommandText = sbSql.ToString();
                
                Debug.WriteLine(sbSql.ToString());

                cmd.Parameters.Add("@TEST1", iDB2DbType.iDB2Char);
                cmd.Parameters.Add("@TEST2", iDB2DbType.iDB2Char);

                cmd.Parameters["@TEST1"].Value = "(更新対象レコードのキー)";
                cmd.Parameters["@TEST2"].Value = sValue;

                cmd.ExecuteNonQuery();
            }
            cn.Close();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

※AppendLineを使用していないのは、WindowsCEとソースを共有している為です。あと\は実際には円マークです。

AS400とのODBC接続時にSQL0666エラー(タイムアウト)

ちょっと時間がかかるクエリを投げたら、「SQL0666 – SQL QUERYが指定された時間制限または記憶制限を超えています。 」とi5に言われた。

前に解決方法を書いていたが、画像のリンクが切れていたので再度投稿。

※iSeries Access for WindowsのODBCドライバを利用しています。

image 管理ツールのODBCより、構成画面を開く。

パフォーマンスタブを選択し、下部にある拡張ボタンを押す

image 「照会タイムアウトを使用可能にする」のチェックボックスを外す。

DB2上での型変換

AS400(i5)のDB2上での型変換のメモ。

※この表現であっているのだろうか・・・

日付型→文字列(yyyymmdd)

REPLACE(CAST(CURRENT_DATE AS VARCHAR(10)), ‘-‘, ”)

日付型→数値(yyyymmdd)

CAST(REPLACE( CAST(CURRENT_DATE AS VARCHAR(10)), ‘-‘, ”) as INTEGER)

DBが変わるといつもSQLリファレンスの変換関数とにらめっこ。