バルクバインド(BULK BIND)の例
セレクト結果を一行づつ処理したいってとき、BULK BIND(BULK FETCHもあるみたい)っていうこともoracleではできるんですね。
-- バルクバインドの例 SET SERVEROUTPUT ON DECLARE TYPE TLINE IS TABLE OF テーブル名%ROWTYPE INDEX BY BINARY_INTEGER; vLINE TLINE; BEGIN SELECT * BULK COLLECT INTO vLINE FROM テーブル名; FOR i IN 1 .. vLINE.COUNT LOOP DBMS_OUTPUT.PUT_LINE('No=' || vLINE(i).カラム名); END LOOP; DBMS_OUTPUT.PUT_LINE('取得行=' || vLINE.COUNT); END; /
参照は以下。
連載 PL/SQLを使ってみよう!第61回「バルク・バインド(SELECT BULK COLLECT INTOの場合)」 | 集合研修 システム・テクノロジー・アイ銀座会場
ちなみに、BULK FETCHは以下。
レコード確認してからのINSERT
レコードがない場合に限りinsertする方法。キーにしてエラーにすればよいって言われるのはわかっているけど、エラーメッセージ見たくない(見せたくない)人向け。
INSERT INTO テーブル(col1, col2) SELECT '値1', '値2' FROM DUAL WHERE NOT EXISTS(SELECT 'X' FROM テーブル WHERE col1 = '確認したい値');
テーブルの検索結果をNOT EXISTSで判定して、INSERT SELECTでインサートする。
参考サイトは以下。
Oracle NVARCHAR2(1600)で1600文字入らない件
NVARCHAR2のカラムを大きくして大量文字を入力しようとすると以下のエラーが発生して入力できない。
エラー:: ORA-01461 : LONG値はLONG列にのみバインドできます。
ググってみたところ、
http://www.projectgroup.info/tips/Oracle/errorcode/ORA01461.html
のサイトが出てきた。
とのことでバージョンを確認したところ、こちらの環境はOracle Clientは11.2.0.4でした。残念。で、エラーメッセージが崩壊しているのは置いておいて、どこまで入るのだろうと根気強く入力値を変化した結果、1333文字までしか入らないことがわかった。
NLS_LANG=JAPANESE_JAPAN.JA16SJISTILDE
と指定しているのでShift_JIS(2byte)なんだけど、1333×3=3999つまり4000byte境界があるっぽい(内部で3byteで計算してるのか?)。
なんだかとても納得行かない仕様。
ちなみに確認したOracleサーバ側のバージョンは11.2。
Oracle NVARCHAR2を文字列連結するときの注意
検索したい該当カラムがNVARCHAR2でも連結すると暗黙変換でVARCHAR2となるらしく、4000byte以上はエラーとあるため、以下のようにTO_CLOB('')を連結しとく必要がある。
SQL> select col1 from foo_table where (TO_CLOB('') || col1 || col2) like '%検索%';
確認したOracleのバージョンは11.2
MacOS Xのはがきデザインキットが起動しない件
日本郵政の年賀状ソフトウェア「はがきデザインキット」を2015年の年末に使っていたのに2016年になってからなぜか使えなくなっていた。
ダブルクリックしてもソフトウェアが起動しない。コマンドラインから起動してみたら以下のようになる。
$ cd /Applications/ $ open -a はがきデザインキット LSOpenURLsWithRole() failed for the application /Applications/はがきデザインキット.app with error -10810. $
これだとわからないのでコンソール.appを起動して見てみた。
2016/01/17 10:00:11.423 はがきデザインキット[2427]: renaming failed with this error: Error Domain=NSCocoaErrorDomain Code=513 "“MacOS”へのアクセス権がないため、“はがきデザインキット”を移動できませんでした。" UserInfo=0x21a800 {NSSourceFilePathErrorKey=/Applications/はがきデザインキット.app/Contents/MacOS/はがきデザインキット, NSUserStringVariant=(
Move
), NSFilePath=/Applications/はがきデザインキット.app/Contents/MacOS/はがきデザインキット, NSDestinationFilePath=/Applications/はがきデザインキット.app/Contents/MacOS/はがきデザインキット_32, NSUnderlyingError=0x218b60 "操作を完了できませんでした。
アクセス権がありません"}
なんかパーミッションがないみたいなので以下を実行
$ cd はがきデザインキット.app/ $ cd Contents/ $ ls -l total 16 -rwxr-xr-x@ 1 root wheel 1926 11 29 14:44 Info.plist drwxr-xr-x@ 3 root wheel 102 11 29 14:44 MacOS -rwxr-xr-x@ 1 root wheel 8 10 28 2014 PkgInfo drwxr-xr-x 8 root wheel 272 11 29 14:44 Resources $ ls -alF MacOS total 72 drwxr-xr-x@ 3 root wheel 102 11 29 14:44 ./ drwxr-xr-x@ 6 root wheel 204 11 29 14:44 ../ -rwxr-xr-x@ 1 root wheel 34604 10 28 2014 はがきデザインキット* $ sudo chmod 777 MacOS Password: $
この後、ダブルクリックしてみたところ起動成功。OSバージョンアップしたわけでもソフトウェアをバージョンアップしたわけでもないのでこうなってしまった原因は不明。
で、起動成功後、バージョンアップを促される。なのでバージョンアップした。
バージョンアップした後、変更したディレクトリパーミッションだとまずいので見てみたところ、
$ pwd /Applications/はがきデザインキット.app/Contents $ ls -alF total 16 drwxr-xr-x@ 6 root wheel 204 1 17 10:06 ./ drwxr-xr-x 3 root wheel 102 1 17 10:06 ../ -rwxr-xr-x@ 1 root wheel 1926 1 17 10:06 Info.plist* drwxr-xr-x@ 3 root wheel 102 1 17 10:06 MacOS/ -rwxr-xr-x@ 1 root wheel 8 11 22 16:08 PkgInfo* drwxr-xr-x 8 root wheel 272 1 17 10:06 Resources/ $ ls -alF MacOS total 64 drwxr-xr-x@ 3 root wheel 102 1 17 10:06 ./ drwxr-xr-x@ 6 root wheel 204 1 17 10:06 ../ -rwxr-xr-x@ 1 root wheel 31252 11 22 16:08 はがきデザインキット* $
ディレクトリのパーミッションは元どおりになっている。これで起動できないのかと思っていたけど普通に起動できる。
エラーメッセージでは"_32"(32bitかよ)にリネームしようとしてパーミッションがないとか言っているんで、実はまずいバージョンを掴まされてただけ?
Javaスレッドで異なるインスタンスでも同期するためには
Javaでスレッドで同期するにはsynchronizedを使用するが、
synchronized public void foo() { .... }
や
public void foo() { synchronized (this) { .... } }
とした場合、同じインスタンスでの同期となる。
スレッドが異なるインスタンスを使用して同期しなきゃいけない時は、同期用オブジェクトをsynchronizedに指定してやれば良い。例ではクラス変数を参照して同期している。
package com.foobar.console; /** * スレッド同志で異なるインスタンスでも同期できるかのテスト */ public class Test00 { private static final int MAX_THREAD = 500; public static int counter = 0; public static final Object LOCK = new Object(); // 同期用オブジェクト public static void main(String[] args) { // スレッド生成 MyThread[] threads0 = new MyThread[MAX_THREAD]; MyThread[] threads1 = new MyThread[MAX_THREAD]; for (int i = 0; i < MAX_THREAD; i++) { threads0[i] = new MyThread(new Counter()); threads1[i] = new MyThread(new Counter()); threads0[i].start(); threads1[i].start(); } // スレッドが全て終了するのを待つ for (int i = 0; i < MAX_THREAD; i++) { try { threads0[i].join(); threads1[i].join(); } catch (InterruptedException e) { System.out.println(e); } } // カウンタを表示 System.out.println(counter); } } /** * スレッドクラス */ class MyThread extends Thread { private Counter counter = null; public MyThread(Counter counter) { this.counter = counter; } public void run() { this.counter.countUp(); } } /** * カウンタクラス */ class Counter { public void countUp() { synchronized (Test00.LOCK) { System.out.print("."); int n = Test00.counter; // カウンタ値を読み込み System.out.print("o"); Test00.counter = n + 1; // 加算してカウンタに設定 System.out.print("O"); } } }
参考にしたのは以下のサイト。