【Oracle】指定日から連続した日付を取得

SQLで指定日から連続した日付を取得します。
集計画面で日ごとの合計を表示したい場合の親テーブルとして利用できます。

  • 例1(ALL_CATALOGを利用)

    SELECT TO_DATE('20150101', 'YYYYMMDD') + ROWNUM -1 AS DCOL FROM ALL_CATALOG WHERE TO_DATE('20150101', 'YYYYMMDD') + ROWNUM -1 <= TO_DATE('20150131', 'YYYYMMDD')ORDER BY 1;
    

    FROM句には指定日から連続した日付の範囲分の行を持っている必要があります。
    今回の例では「ALL_CATALOG」を利用していますが、
    そもそも参照権限がない場合もあるので、1~31までのNoだけを持つ空テーブルを利用します。

  • 例2(ALL_CATALOGの代わりに1~31までのNoだけを持つ空テーブルを利用)

    SELECT TO_DATE('20150101', 'YYYYMMDD') + ROWNUM -1 AS DCOL FROM (SELECT LEVEL id FROM DUAL CONNECT BY LEBEL <= 31) WHERE TO_DATE('20150101', 'YYYYMMDD') + ROWNUM -1 <= TO_DATE('20150131', 'YYYYMMDD')ORDER BY 1;
    
  • 例3(1~31までのNoだけを持つ空テーブルだけを利用)

    SELECT SYSDATE + LEVEL AS HIZEKE FROM DUAL CONNECT BY LEBEL <= 31;
    

【Oracle】順位付け

SQLで点数の高い順位を採番します。
その際、同点の場合、1, 1, 3のように採番します。

SELECT RANK() OVER(ORDER BY 項目 DESC) FROM テーブル名

【Oracle】SQLで表記揺れ

住所の登録システムを作っているときにたまに要件で出てくる表記揺れ。
ひらがなは全て半角カタカナに変換したり、
括弧も全て()に変換したりします。

Oracle10gからの機能であるUTL_I18NパッケージのTRANSLITERATEファンクションを利用します。
下記に例を示しておきます。

テキトーな仕様
全角英数字:全て半角英数字に変換
全角ひらがな、カタカナ:全て半角カタカナに変換
前後の中間の空白:全角、半角問わず削除
全角半角の括弧{}、「」、<>、():全て()に変換
全角記号:半角記号に変換
全角半角のハイフン:全て-に変換
CREATE OR REPLACE FUNCTION CONVERSION_TEST(
    IN_CHAR VARCHAR
) RETURN VARCHAR
IS
BEGIN
RETURN
    UTL_I18N.TRANSLITERATE(
        TRANSLATE(
            UPPER(TO_SINGLE_BYTE(REPLACE(REPLACE(IN_CHAR,' '),' ')))
            ,'{}「」<>()ー-!#$%'
            ,'()()()()--!#$%'
            )
        ,'kana_hwkatakana')
    ;
END CONVERSION_TEST;

記号、括弧、ハイフンは全部書くとキリないので、省略しています。
「kana_hwkatakana」の部分は他にも色々あるようです。

【Java】セッションとクッキーについて

セッションとクッキーについてメモ。

  • クッキーについて

    • 保存場所

      C:\Users\ユーザ名\AppData\Local\Microsoft\Windows\Temporary Internet Files
      
    • ファイル名

      Cookie:ユーザ名@サイト名/
      
    • ブラウザメモリに保存されているクッキーの値が最優先
      ファイルに保存されたクッキーの値を変更しても
      ブラウザを閉じない限り、異なるIEで繋いでもブラウザで取得済の
      ブラウザメモリのクッキーの値を使用する。
      ブラウザを閉じて繋ぎなおすと、ファイルに保存されたクッキーの値を使用する。

      ただしクッキーの値の変更はツールを使用しないと有効にならない。
      手書きで変更しても読み取れずに2番目の動作時にクッキーの値がNULLとなる。

  • セッションについて

    • 保存場所
      ブラウザメモリまたはクッキーのファイルに保存。
      キー名はJSESSIONIDであり、クッキーの値が優先される。
    • セッションハイジャック
      セッションIDはサーバーとやり取りしている中でブラウザが自動でサーバーへ送信しているが、
      下記の記述で明示的に直接指定することも可能。

      変更前
      セッションIDはブラウザメモリまたはクッキーの値を自動でサーバーへ送信

      http://z-area.net/コンテキスト名?request1=test1&request2=test2
      

      変更後
      セッションIDはURLの値をサーバーへ送信

      http://z-area.net/コンテキスト名;jsessionid=12345?request1=test1&request2=test2
      

      12345のセッションIDが正規のユーザのものである場合、
      変更後のリクエストは正常に処理される。

      ログイン画面を表示した時点でセッションIDが採番されるので、
      セッションハイジャックを防ぐにはログイン成功後にセッションIDを採番し直す。

  • ツール
    クッキー書き換え:IECookiesView(日本語化可能)
    HTTP情報参照:ieHTTPHeaders

【Java】JavaでXML解析

JavaでXMLを解析します。

  • XMLファイル

    <?xml version="1.0" encoding="UTF-8"?>
    <sample>
    	<location>
    		<area name="area1">
    			<shop type="kanto_shopName1" required="111" />
    		</area>
    		<area name="area2">
    			<shop type="sikoku_shopName1" required="222" />
    			<shop type="sikoku_shopName2" required="333" />
    		</area>
    		<area name = "area3">
    			<shop type="kansai_shopName1" required="444" />
    			<shop type="kansai_shopName2" required="555" />
    			<shop type="kansai_shopName3" required="666" />
    		</area>
    	</location>
    </sample>
    
  • XMLファイル読取

    /*
     * メイン処理を実行します。
     * @param args 引数
     */
    public static void main(String[] args) {
    
        try {
            File fileObject = new File("src/conf/test.xml");
            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = docBuilder.parse(fileObject);
            NodeList nodeList = document.getChildNodes();
            scanNodes(nodeList);
            System.out.println("マップサイズ:" + resultMap.size());
    
            for (String key : resultMap.keySet()) {
                List<Z_XmlAnalyzerBean> list = resultMap.get(key);
                System.out.print("全体キーは" + key + "@");
                for (int i=0; i<list.size(); i++) {
                    Z_XmlAnalyzerBean bean = list.get(i);
                    System.out.print(bean.getKey() + ":" + bean.getValue() + ", ");
                }
                System.out.println("");
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • XMLファイル解析

    /*
     * ノードリストを再帰的に解析します。
     * @param nodeList ノードリスト
     */
    public static void scanNodes(NodeList nodeList) {
    
        for (int i=0; i<nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (Node.ELEMENT_NODE == node.getNodeType()) {
                NamedNodeMap nodeMap = node.getAttributes();
                if (nodeMap != null) {
                    for (int j=0; j<nodeMap.getLength(); j++) {
                        if (nodeMap.item(j).getNodeName().equals("name")) {
                            String mapKey = nodeMap.item(j).getNodeValue();
                            List<Z_XmlAnalyzerBean> list = new ArrayList<Z_XmlAnalyzerBean>();
                            resultMap.put(mapKey, list);
                        }
    
                        if (nodeMap.item(j).getNodeName().equals("type")) {
                            String mapValueKey = nodeMap.item(j).getNodeName();
                            String mapValueValue = nodeMap.item(j).getNodeValue();
                            System.out.println(mapValueKey + ":" + mapValueValue);
    
                            Node parentNode = node.getParentNode();
                            NamedNodeMap parentNodeMap = parentNode.getAttributes();
                            String parentZokuseiName = parentNodeMap.item(0).getNodeName();
                            String parentZokuseiValue = parentNodeMap.item(0).getNodeValue();
                            System.out.println("親:" + parentZokuseiName + "," + parentZokuseiValue);
    
                            List<Z_XmlAnalyzerBean> list = resultMap.get(parentZokuseiValue);
                            Z_XmlAnalyzerBean bean = new Z_XmlAnalyzerBean();
                            bean.setKey(mapValueKey);
                            bean.setValue(mapValueValue);
                            list.add(bean);
                        }
                    }
                }
            }
    
            if (node.hasChildNodes()) {
                scanNodes(node.getChildNodes());
            }
        }
    }
    
  • XML要素格納Bean

    public class Z_XmlAnalyzerBean {
    
        private String key = null;
        private String value = null;
    
        public String getKey() {
            return key;
        }
        public void setKey(String key) {
            this.key = key;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }
    

【Java】Javaからシェル呼び出し

JavaからWindowsのコマンドプロンプトを呼び出して、
ファイルコピーは実施したことありましたが、
現場の実作業でLinuxのシェルを呼び出して欲しいと言われました。
普通はナイナイと話していたのに実際にあるとは驚きました。

自宅で試してみました。

  • 呼ばれる側

    cat /home/ユーザ名/java/シェル名.sh
    #!/bin/sh
    echo "Hellow World !!"
    cd aaaa
    

    標準出力とエラー出力の両方があった場合を試したかったので、
    わざと存在しないディレクトリに移動しています。
    実行権限をつけておきます。

    chmod -x シェル名
    
  • 呼び出し側

    /**
     * メイン処理
     * @param args 引数
     */
    public static void main(String[] args) {
    
        ArrayList<String> cmd = new ArrayList<String>();
        cmd.add("/home/ユーザ名/java/シェル名.sh");
    
        try {
                ProcessBuilder processBuilder = new ProcessBuilder(cmd);
                processBuilder.redirectErrorStream(true);
                Process process = processBuilder.start();
                InputStream inputStream = process.getInputStream();
                printInputStream(inputStream);
                System.out.println(process.waitFor());
        } catch (Exception e) {
                e.printStackTrace();
        }
    }
    
    /**
     * 入力ストリームの内容を出力する。
     * @param inputStream 入力ストリーム
     * @throws IOException [入出力エラーが発生した場合]
     */
    public static void printInputStream(InputStream inputStream) throws IOException {
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));) {
                for (;;) {
                    String line = bufferedReader.readLine();
                    if (line == null) {
                        break;
                }
                    System.out.println(line);
            }
        }
    }
    
  • 実行結果

    javac クラス名.java
    java クラス名
    
    Hellow World !!
    /home/ユーザ名/java/シェル名.sh: line 3: cd: aaa: そのようなファイルやディレクトリはありません
    1
    

    ProcessBuilderクラスのredirectErrorStreamをtrueにしたので、
    標準出力とエラー出力が同時に出力されています。
    ただしこのバッファは1024バイトまでらしいです。
    ⇒echoで1050バイトほど出力するようなシェルにしてみましたが、
     出力できてしまいました。謎です。

    また、異常終了したので戻り値も「1」になっています。

  • 恥ずかしながらはまったこと
    シェル名.shをWindowsで作成していたため、改行コードがCRLFのままでした。
    改行コードがCRLFのままシェルを実行すると、下記エラーが出力されます。

    -bash: ./シェル名.sh: /bin/bash^M: bad interpreter: そのようなファイルやディレクトリはありません
    

    「^M」が出ているのがわかります。
    sedコマンドでLFに置換しました。

    sed -i 's/r//' /home/ユーザ名/java/シェル名.sh
    

【Eclipse】Eclipse再設定

Eclipseで色々いじりすぎて復元できなくなった場合の再設定メモ。

EclipseはIndigoの3.7.2を利用しています。

  • 壊れたEclipse
    【モジュール】
    EclipseのworkplaceディレクトリからSVN管理されていないプロジェクトをコピーしてどこかに保存する。

    【設定】
    「ファイル」-「エクスポート」を選択する。
    「一般」-「設定」を選択し、「次へ」ボタンを押下する。
    全てをエクスポートにチェックを入れ、「宛先設定ファイル」を指定し、「完了」ボタンを押下する。

  • 新しいEclipse
    【モジュール】
    どこかにコピーしておいたプロジェクトを新しいworkplaceに配置。
    「ファイル」-「インポート」を選択する。
    「一般」-「既存プロジェクトをワークスペースへ」を選択し、「次へ」ボタンを押下する。
    ルート・ディレクトリの選択にチェックを入れ、プロジェクトを選択し、「完了」ボタンを押下する。
    SVN管理されているプロジェクトはチェックアウトする。

    【設定】
    「ファイル」-「インポート」を選択する。
    「一般」-「設定」を選択し、「次へ」ボタンを押下する。
    ソース設定ファイルを選択し、「完了」ボタンを押下する。

【Oracle】SQLPlusで空白除去

OracleのSQLPlusでSELECT結果をspoolでファイル出力した際、
CHAR型やVARCHAR2型の出力結果がサイズにあうように自動で空白埋めされてしまい、
想定結果ととても比較し難い。

「SET TRIMSPOOL ON」にしても空白が削除されないのは、
これが「行末のトリム処理を制御する」からのようです。
「項目ごとのトリム処理を制御する」なら便利だったのに。

色々調べてもSQLPlusの設定だけでやるのは無理なようで、
結局下記のようにパイプでつなげることにしました。

SELECT 項目1 || 't' || 項目2 || 't' || 項目3 FROM テーブル名;

TeraTeramで自動ログイン

TeraTermで接続情報を毎回手打ちして、
ログインするのが面倒なので、自動ログインします。

デスクトップでも好きな場所に「ファイル名.ttl」ファイルを作成します。
ファイルが「ttpmacro.exe」に関連付けられていない場合、
TeraTermのインストールディレクトリに存在する「ttpmacro.exe」に関連付けを行います。

ファイルの中身を記載します。

hostname = 'IPアドレスまたはホスト名'
username = 'ユーザ名'
passfile = 'D:/任意のディレクトリ/任意のファイル名'
keyfile = 'D:/任意のディレクトリ/秘密鍵のファイル名'

getpassword passfile username userpass

command = hostname
strconcat command ':22 /ssh /KR=UTF-8 /KT=UTF-8 /auth=publickey /user='
strconcat command username
strconcat command ' /passwd='
strconcat command userpass
strconcat command ' /keyfile='
strconcat command keyfile

connect command

end

初回ログインで1度パスワードを聞かれますが、
2回目からはファイルを自動参照します。

【bat】WinBatで自動ログイン

ファイルサーバにログインする際、接続情報を毎回手打ちして、
ログインするのが面倒なので、自動ログインします。

デスクトップでも好きな場所に「ファイル名.bat」ファイルを作成します。

ファイルの中身を記載します。

@echo off
SET COMMON_USR=ユーザ名
SET COMMON_PASS=パスワード

echo ホスト名ログイン中
net use ホスト名/ディレクトリ名 /USER:%COMMON_USR% %COMMON_PASS%

pause

接続できない場合、接続情報が残ってしまっていることがあるので、
コマンドプロンプト上で下記コマンドで削除します。

net use ホスト名/ディレクトリ名 /delete