トップ 最新 追記

Masa's blog

検索キーワード:

2009年07月01日 jvim-3.0 on Libretto U100/190DSB [長年日記]

_ jvim-3.0 on Libretto U100/190DSB

Slackware-12.2のvim-7.2は頻繁にフリーズする。結局昔から使ってるjvim-3.0をソースからインストールし直した。快調。


2009年07月03日 DVD on Libretto U100 [長年日記]

_ DVD on Libretto U100

せっかくwritableなDVDドライブが付いているので、Slackware-12.2DVD Videoを焼いてみたい。

まずmencoderを使って

mencoder dvd://1 -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=720:480  -lavcopts vcodec=mpeg2video:vbitrate=800:acodec=ac3:abitrate=224 -ofps 24 -o movie.mpg

としてDVDからmovie.mpgを作成し、dvdauthor.xmlを以下のように作成して

<dvdauthor>
    <vmgm />
    <titleset>
        <titles>
            <pgc>
                <vob file="movie.mpg" />
            </pgc>
        </titles>
    </titleset>
</dvdauthor>

dvdauthorコマンドを実行して

rm -fr dvd; dvdauthor -o dvd -x dvdauthor.xml

DVD Videoの構成にオーサリングを行ったところ、

$ ls -alR dvd
dvd:
合計 16
drwxr-xr-x 4 m-ito m-ito 4096 2009-07-03 08:46 .
drwxr-xr-x 3 m-ito m-ito 4096 2009-07-03 09:15 ..
drwxr-xr-x 2 m-ito m-ito 4096 2009-07-03 08:46 AUDIO_TS
drwxr-xr-x 2 m-ito m-ito 4096 2009-07-03 08:49 VIDEO_TS

dvd/AUDIO_TS:
合計 8
drwxr-xr-x 2 m-ito m-ito 4096 2009-07-03 08:46 .
drwxr-xr-x 4 m-ito m-ito 4096 2009-07-03 08:46 ..

dvd/VIDEO_TS:
合計 965728
drwxr-xr-x 2 m-ito m-ito      4096 2009-07-03 08:49 .
drwxr-xr-x 4 m-ito m-ito      4096 2009-07-03 08:46 ..
-rw-r--r-- 1 m-ito m-ito      6144 2009-07-03 08:49 VIDEO_TS.BUP
-rw-r--r-- 1 m-ito m-ito      6144 2009-07-03 08:49 VIDEO_TS.IFO
-rw-r--r-- 1 m-ito m-ito     22528 2009-07-03 08:49 VTS_01_0.BUP
-rw-r--r-- 1 m-ito m-ito     22528 2009-07-03 08:49 VTS_01_0.IFO
-rw-r--r-- 1 m-ito m-ito 987860992 2009-07-03 08:49 VTS_01_1.VOB

AUDIO_TSディレクトリ以下が空っぽになっている。何が問題なのか?。


2009年07月04日 DVD-VIDEO焼きスクリプト on Libretto U100 [長年日記]

_ DVD-VIDEO焼きスクリプト on Libretto U100

念願のDVD-VIDEO焼きスクリプト完成。AUDIO_TSディレクトリ以下が空っぽは問題なかった。

dvd2dvd.sh

#! /bin/sh
if [ "X$1" = "X-h" -o "X$1" = "X--help" ]
then
    echo "Usage : dvd2dvd.sh [-sp speed] [-rw] [-2] [-s hh:mm:ss] [ -e hh:mm:ss] [-t title] [-c chapter] [-a aspect] [-vb vbitrate] [-ab abitrate] [-f fps] [-al audio_lang] [-sl subtitle_lang]"
    echo ""
    echo "  -sp speed           : write power (default 4)"
    echo "  -rw                 : DVD-RW"
    echo "  -2                  : 2-pass"
    echo "  -s start_time       : start position time"
    echo "  -e end_time         : pass time"
    echo "  -t title            : title number (default 1)"
    echo "  -c chapter          : chapter (default 1)"
    echo "  -a aspect           : aspect 16/9 or 4/3 (default 16/9)"
    echo "  -vb vbitrate        : video bitrate (kbit) (default 5000)"
    echo "  -ab abitrate        : audio bitrate (kbit) (default 192)"
    echo "  -f fps              : frame per second 30000/1001 or 24000/1001 (default 30000/1001)"
    echo "  -al audio_lang      : audio language (default ja,en)"
    echo "  -ai audio_id        : audio id"
    echo "  -sl subtitle_lang   : subtitle language (default none)"
    echo "  -si subtitle_id     : subtitle id "
    exit 0
fi
#
speed="4"
rw=no
pass="1"
start=""
end=""
title="1"
chapter="1"
aspect=16/9
vbitrate=5000
abitrate=192
ofps=30000/1001
alang="ja"
aid=""
slang=""
sid=""
#
while [ $# != 0 ]
do
    case $1 in
    -sp )
        shift
        speed="$1"
        ;;
    -rw )
        rw=yes
        ;;
    -2 )
        pass=2
        ;;
    -s )
        shift
        start="-ss $1"
        ;;
    -e )
        shift
        end="-endpos $1"
        ;;
    -t )
        shift
        title="$1"
        ;;
    -c )
        shift
        chapter="$1"
        ;;
    -a )
        shift
        aspect=$1
        ;;
    -vb )
        shift
        vbitrate="$1"
        ;;
    -ab )
        shift
        abitrate="$1"
        ;;
    -f )
        shift
        ofps="$1"
        ;;
    -al )
        shift
        alang="$1"
        ;;
    -ai )
        shift
        aid="$1"
        ;;
    -sl )
        shift
        slang="$1"
        ;;
    -si )
        shift
        sid="$1"
        ;;
    esac
    shift
done
#
if [ "X${alang}" = "X" ]
then
    alang_opt=""
else
    alang_opt="-alang ${alang}"
fi
#
if [ "X${aid}" = "X" ]
then
    aid_opt=""
else
    aid_opt="-aid ${aid}"
fi
#
if [ "X${slang}" = "X" ]
then
    slang_opt=""
else
    slang_opt="-slang ${slang}"
fi
#
if [ "X${sid}" = "X" ]
then
    sid_opt=""
else
    sid_opt="-sid ${sid}"
fi
#
function menc() {
	pass=$1
	filename=$2

	if [ "X${pass}" = "X0" ]
	then
		vpass=""
	else
		vpass="vpass=${pass}:"
	fi

	mencoder dvd://${title} -chapter ${chapter} \
		${start} ${end} \
		${alang_opt} ${aid_opt} \
		${slang_opt} ${sid_opt} \
		-oac lavc \
		-ovc lavc \
		-of mpeg \
		-mpegopts format=dvd:tsaf \
		-vf scale=720:480,harddup \
		-srate 48000 \
		-af lavcresample=48000 \
		-lavcopts ${vpass}vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=${vbitrate}:keyint=18:vstrict=0:acodec=ac3:abitrate=${abitrate}:aspect=${aspect} \
		-ofps ${ofps} \
		-o ${filename}
}
#
if [ "X${pass}" = "X1" ]
then
	menc 0 dvd2dvd.mpg.tmp
else
	menc 1 /dev/null
	menc 2 dvd2dvd.mpg.tmp
fi
#
cat >dvd2dvd.xml.tmp <<_EOF_
<dvdauthor>
    <vmgm />
    <titleset>
        <titles>
            <pgc>
                <vob file="dvd2dvd.mpg.tmp" chapters="0,5:00,10:00,15:00,20:00,25:00,30:00,35:00,40:00,45:00,50:00,55:00,1:00:00,1:05:00,1:10:00,1:15:00,1:20:00,1:25:00,1:30:00,1:35:00,1:40:00,1:45:00,1:50:00,1:55:00,2:00:00,2:05:00,2:10:00,2:15:00,2:20:00,2:25:00,2:30:00,2:35:00,2:40:00,2:45:00,2:50:00,2:55:00,3:00:00" />
            </pgc>
        </titles>
    </titleset>
</dvdauthor>
_EOF_
dvdauthor -o dvd2dvd.dir.tmp -x dvd2dvd.xml.tmp
#
mkisofs -o dvd2dvd.img.tmp -dvd-video dvd2dvd.dir.tmp/
#
eject /dev/dvd
echo ""
echo ================================================
echo Change to BLANK DVD-R and hit ENTER to continue.
echo ================================================
read
#
if [ "X${rw}" = "Xyes" ]
then
	dvdrecord dev=2,0,0 speed=${speed} blank=fast
fi
dvdrecord -v dev=2,0,0 speed=${speed} -dao dvd2dvd.img.tmp
eject /dev/dvd
#
rm -fr dvd2dvd.*.tmp

参考 :


2009年07月05日 キーボードから輝度コントロール等 on Libretto U100 [長年日記]

_ キーボードから輝度コントロール等 on Libretto U100

fnfxdを使うとできるらしい。

インストール

$ tar xvzf fnfx-0.3.tar.gz
$ cd fnfx-0.3
$ ./configure && make
# make install

後述するfnfxdが何故か/usr/local/etc/fnfx/を見ずに/etc/fnfx/を見てしまうので、シンボリックリンクをはる。

# ln -s /usr/local/etc/fnfx /etc/fnfx

それと(よくわからない)クライアントのfnfxが参照する~/.fnfxrcをサンプルからコピーする。

$ cp /etc/fnfx/fnfxrc_example ~/.fnfxrc

fnfxd(デーモン)をブート時に起動するように設定。

/etc/rc.d/rc.local

if [ -x /usr/local/sbin/fnfxd ]
then
        /usr/local/sbin/fnfxd start
fi

東芝ラップトップのACPIモジュールをブート時にロードするように設定。

/etc/rc.d/rc.module

/sbin/modprobe toshiba_acpi

これで、Fn+F6(輝度ダウン)、Fn+F7(輝度アップ)ができるようになる。その他のキーアサインについては、/etc/fnfx/fnfxd.confを参照。


2009年07月06日 myh.no-ip.org(libretto 100) linux-2.4.37.2 Version UP [長年日記]

_ myh.no-ip.org(libretto 100) linux-2.4.37.2 Version UP

サーバ(myh.no-ip.org on Libretto 100)のカーネルをlinux-2.4.37.2にバージョンアップ。すると以前から出ていた

request_module[net-pf-10]: waitpid(3788,...) failed, errno 1

のメッセージが出なくなっていた(^o^)/。さらに、modprobe.oldがゾンビプロセスになってた件も解決していた(^O^)/。

_ fnfxd breaks Wireless LAN

fnfxdを使うと輝度コントロール等ができると書いて喜んでいたのだが、Libretto U100では、なぜか無線LANがつながらなくなる現象が頻発。とりあえず使用を中止することに...。


2009年07月10日 Java儂(わし)的解釈によるメモ(JDBC + MySQL編) [長年日記]

_ Java儂(わし)的解釈によるメモ(JDBC + MySQL編)

JavaからDBMS(MySQL)にJDBC経由で接続してみる。例によって用語、用法等は思い込みである部分が見受けられると思うが、御容赦願う。

準備

Slackware-12.xに標準でインストールされるMySQL-5.xをそのまま利用する。

JDBCドライバの取得

mysql-connector-java-5.0.8.tar.gzを取得(http://dev.mysql.com/downloads/connector/j/)

$ tar xvzf mysql-connector-java-5.0.8.tar.gz
$ cp mysql-connector-java-5.0.8/mysql-connector-java-5.0.8-bin.jar .

mysql-connector-java-5.0.8-bin.jarをどこかグローバルな場所(例えば/usr/local/jdk/みたいな)に置いて、

CLASSPATH=${CLASSPATH}:/usr/local/jdk/mysql-connector-java-5.0.8-bin.jar; export CLASSPATH

しておくのも良いかも。

データベース領域の初期化

mysqldを起動するに当たって、一度だけ実行する必要がある。

# mysql_install_db --user=mysql
mysqld起動スクリプトの修正

JDBC経由でアクセスするために起動オプションを修正する(/etc/rc.d/rc.mysqld)。

#SKIP="--skip-networking"  <-- コメントアウト
MySQLコンフィグファイル設定

デフォルト文字コード、デフォルトストレージエンジンの設定。

標準のストレージエンジンであるMyISAMは速度は早いが、トランザクションがサポートされていない。非標準のストレージエンジンであるInnoDBMyISAMに比べると速度が劣るがトランザクションをサポートする。

汎用機畑で育った私としてはトランザクションが無い(すなわちcommit、rollbackが無い)のは信じられないので、デフォルトのストレージエンジンをInnoDBに変更する。

# cp /etc/my-small.conf /etc/my.cnf
# vi /etc/my.cnf

[client]
##default-character-set = utf8
default-character-set = ujis
[mysqld]
##default-character-set = utf8
default-character-set = ujis
default-storage-engine=innodb
mysqld起動
# chmod +x /etc/rc.d/rc.mysqld; reboot
MySQL管理者(root)のパスワード設定
# mysqladmin -u root password ROOT-PASSWORD
データベース(jdbctestdb)の作成
# mysql -u root -p
Enter password: XXXXXXXXXXXXX <-- ROOT-PASSWORDを入力する
mysql> create database jdbctestdb character set ujis;
mysql> quit
一般ユーザ(m-ito)にデータベースへのアクセス権を設定
# mysql -u root -p jdbctestdb
Enter password: XXXXXXXXXXXXX <-- ROOT-PASSWORDを入力する
mysql> grant all on jdbctestdb.* to 'm-ito'@'localhost' identified by 'USER-PASSWORD';
mysql> quit
一般ユーザ用MySQLコンフィグファイル設定

パスワードの設定とデフォルト文字コードの設定。このあたりは必要に応じて...。

$ cp /etc/my-small.conf ~m-ito/.my.cnf
$ chmod 600 ~m-ito/.my.cnf
$ vi ~m-ito/.my.cnf

[client]
password = USER-PASSWORD
##default-character-set = utf8
default-character-set = ujis

サンプルプログラム

//
// 「jdbc mysql」テスト
//
// compile : javac -encoding utf-8 jdbc_mysql.java
// run     : java -cp .:mysql-connector-java-5.0.8-bin.jar jdbc_mysql
//
//import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class jdbc_mysql {

	static Connection conn = null;
	static Statement stmt = null;
	static PreparedStatement pstmt = null;
	static ResultSet rs = null;
	static ResultSetMetaData rsmd = null;

	public static void main(String[] args) {
		try {
//
// JDBC for MySQLのロード
//
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			System.out.println("JDBCドライバをロードしました。");
//
// データベースへの接続
//
//			String url = "jdbc:mysql://localhost/jdbctestdb?useUnicode=true&characterEncoding=SJIS";
			String url = "jdbc:mysql://localhost/jdbctestdb?useUnicode=true&characterEncoding=EUC_JP";
			conn = DriverManager.getConnection(url, "m-ito", "USER-PASSWORD");
			System.out.println("jdbctestdbに接続しました。");
//
// 自動コミット停止(トランザクションの開始)
//
			conn.setAutoCommit(false);
			System.out.println("自動コミットをOFFにしました。");
//
// SQLステートメントオブジェクト生成
//
			stmt = conn.createStatement();
//
// テーブルの削除
//
			try {
				stmt.executeUpdate("drop table member");
				System.out.println("テーブル member を削除しました。");
			} catch(Exception e){
				System.out.println("テーブル member を削除できませんでした(" + e.getMessage() + ")");
			}
//
// テーブルの作成
//
			stmt.executeUpdate(
				"create table member (" +
					"id INT PRIMARY KEY," +
					"name VARCHAR(50)," +
					"job VARCHAR(50)" +
				") engine = innodb"
			);
			System.out.println("テーブル member を作成しました。");
//
// わざと2重にテーブル作成してみる
//
			try {
				stmt.executeUpdate(
					"create table member (" +
						"id INT PRIMARY KEY," +
						"name VARCHAR(50)," +
						"job VARCHAR(50)" +
					")"
				);
				System.out.println("テーブル member を作成しました(2)。");
			} catch(Exception e){
				System.out.println("テーブル member を作成できませんでした(2)(" + e.getMessage() + ")");
			}
//
// 2次インデックス作成
//
			stmt.executeUpdate("create index i_member_name on member(name)");
			System.out.println("インデックスを作成しました。");
//
// タプルの追加
//
			try {
				pstmt = conn.prepareStatement("insert into member (id, name, job) values (?, ?, ?)");
//
// 1件目
//
				pstmt.setInt(1, 1);
				pstmt.setString(2, "伊藤 太郎");
				pstmt.setString(3, "サラリーマン");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// 2件目
//
				pstmt.setInt(1, 2);
				pstmt.setString(2, "山田 太郎");
				pstmt.setString(3, "野球選手");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// 3件目
//
				pstmt.setInt(1, 3);
				pstmt.setString(2, "山田 花子");
				pstmt.setString(3, "タレント");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// わざと3件目をもう一度追加してみる
//
				pstmt.setInt(1, 3);
				pstmt.setString(2, "山田 花子");
				pstmt.setString(3, "タレント");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
			} catch (Exception e) {
				System.out.println("インサートできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの検索
//
			try {
//
// クエリの実行
//
				pstmt = conn.prepareStatement("select * from member where id >= ?");
				pstmt.setInt(1, 1);
				rs = pstmt.executeQuery();
//
// 1件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// 2件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// 3件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// わざと存在しない4件目を取り出してみる
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
			} catch (Exception e) {
				System.out.println("セレクトできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの更新
//
			try {
//
// 更新ステートメント実行
//
				pstmt = conn.prepareStatement("update member set job = ? where name = ?");
				pstmt.setString(1, "裁判官");
				pstmt.setString(2, "山田 太郎");
				pstmt.executeUpdate();
				System.out.println("アップデートしました。");
//
// 更新結果を取り出すクエリの実行
//
				pstmt = conn.prepareStatement("select * from member where name = ?");
				pstmt.setString(1, "山田 太郎");
				rs = pstmt.executeQuery();
//
// クエリ結果の取り出し
//
				rs.next();
				System.out.println("アップデート結果(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
			} catch (Exception e) {
				System.out.println("アップデートできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの削除
//
			try {
//
// 削除ステートメント実行
//
				pstmt = conn.prepareStatement("delete from member where name like ?");
				pstmt.setString(1, "山田%");
				pstmt.executeUpdate();
				System.out.println("デリートしました(" + pstmt.getUpdateCount() + "件)。");
//
// 削除後の状態の検索クエリ実行
//
				pstmt = conn.prepareStatement("select * from member");
				rs = pstmt.executeQuery();
//
// クエリ結果の取り出し
//
				while (rs.next()){
					System.out.println("デリート結果(id=" +
						rs.getInt("id") + ")(name=" +
						rs.getString("name") + ")(job=" +
						rs.getString("job") + ")。");
				}
			} catch (Exception e) {
				System.out.println("デリートできませんでした(" + e.getMessage() + ")");
			}
//
// メタデータの取得
//
			try {
//
// メタデータの取得
//
				rsmd = rs.getMetaData();
//
// カラム数の取得
//
				int numberOfColumns = rsmd.getColumnCount();
				System.out.print("メタデータを取得しました(");
				for (int i = 1; i <= numberOfColumns; i++) {
//
// カラム名称の取得
//
					String name = rsmd.getColumnName (i);
					System.out.print(name + "\t");
				}
				System.out.println(")。");
			} catch (Exception e) {
				System.out.println("メタデータを取得できませんでした(" + e.getMessage() + ")");
			}
//
// コミット(トランザクションの反映)
//
			try {
				conn.commit();
				System.out.println("コミットしました。");
			} catch (Exception e) {
				System.out.println("コミットできませんでした(" + e.getMessage() + ")");
			}
		} catch (SQLException e) {
			System.out.println("SQLException: " + e.getMessage());
			System.out.println("SQLState: " + e.getSQLState());
			System.out.println("VendorError: " + e.getErrorCode());
//
// ロールバック(トランザクションの破棄)
//
			try {
				conn.rollback();
			} catch(Exception e2){
				System.out.println(e2.getMessage());
			}
		} catch(Exception e){
			System.out.println(e.getMessage());
//
// ロールバック(トランザクションの破棄)
//
			try {
				conn.rollback();
			} catch(Exception e2){
				System.out.println(e2.getMessage());
			}
		}

		try {
//
// 検索クエリの結果セットオブジェクトを破棄
//
			rs.close();
//
// SQLステートメントオブジェクトを破棄
//
			stmt.close();
			pstmt.close();
//
// データベースからの切断
//
			conn.close();
		} catch(Exception e){
			System.out.println(e.getMessage());
		}
		System.out.println("jdbctestdbから切断しました。");

	}
}

実行結果

JDBCドライバをロードしました。
jdbctestdbに接続しました。
自動コミットをOFFにしました。
テーブル member を削除しました。
テーブル member を作成しました。
テーブル member を作成できませんでした(2)(Table 'member' already exists)
インデックスを作成しました。
インサートしました。
インサートしました。
インサートしました。
インサートできませんでした(Duplicate entry '3' for key 1)
セレクトしました(id=1)(name=伊藤 太郎)(job=サラリーマン)。
セレクトしました(id=2)(name=山田 太郎)(job=野球選手)。
セレクトしました(id=3)(name=山田 花子)(job=タレント)。
セレクトできませんでした(After end of result set)
アップデートしました。
アップデート結果(id=2)(name=山田 太郎)(job=裁判官)。
デリートしました(2件)。
デリート結果(id=1)(name=伊藤 太郎)(job=サラリーマン)。
メタデータを取得しました(id     name    job     )。
コミットしました。
jdbctestdbから切断しました。

追記

  • stmt.executeUpdate(INSERT|DELETE|UPDATE) の戻り値は更新されたタプル数
  • stmt.executeUpdate(上記以外の更新系SQL) の戻り値は 0
  • エラー発生時は SQLExceptin 発生。getSQLState()にてエラーコードを取得できる。

about Microsoft SQL Server(情報のみ)

Microsoft SQL Server 2005 JDBC Driver

JDBCドライバ(msbase.jar、mssqlserver.jar)を使用した場合(SQLServer2000以前)

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
Connection con = DriverManager.getConnection("jdbc:microsoft:sqlserver://サーバ名:1433","ユーザID","パスワード");

JDBCドライバ(sqljdbc.jar)を使用した場合(SQLServer2005以降)

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection("jdbc:sqlserver://サーバ名:1433","ユーザID","パスワード");

about Oracle(情報のみ)

Oracle JDBC Driver ダウンロード

Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@サーバ名:1521:OracleSID","ユーザID","パスワード");

OracleSID : tnsnames.ora に記述がある。


2009年07月11日 ruby(1.8.x)儂(わし)的解釈によるメモ(DBI + MySQL編) [長年日記]

_ ruby(1.8.x)儂(わし)的解釈によるメモ(DBI + MySQL編)

rubyからDBMS(MySQL)にDBI経由で接続してみる。例によって用語、用法等は思い込みである部分が見受けられると思うが、御容赦願う。

準備

dbi-0.4.1.tar.gzを取得する(http://rubyforge.org/frs/?group_id=234)。

# tar xvzf dbi-0.4.1.tar.gz
# cd dbi-0.4.1/
# gem install dbi
# gem install dbd-mysql

もし上記でdbiがうまくインストール出来なかった場合は、

# ruby setup.rb config
# ruby setup.rb setup
# ruby setup.rb install

を試してみるとよいかも...。

サンプルプログラム

#! /usr/bin/ruby
#
require 'rubygems'
require 'dbi'
#
# データベースへの接続
#
dbh = DBI.connect('DBI:Mysql:dbitestdb', 'm-ito', 'USER-PASSWORD')
puts("データベース(dbitestdb)に接続しました。")
#
# 文字コードの設定(MySQL依存)
#
dbh.do('SET NAMES ujis')
puts("日本語文字コードをujisに設定しました(MySQL依存設定)。")
#
# 自動コミットの停止
#
##dbh.do('SET AutoCommit = 0')
dbh['AutoCommit'] = false
puts("自動コミット停止しました(トランザクションの開始)。")
#
# トランザクション(1)
#
dbh.transaction {|dbh|
#
# テーブルの削除
#
	begin
		sql = <<SQL
			drop table member
SQL
		dbh.do(sql)
		puts "テーブルの削除に成功しました。"
	rescue => e
		puts "テーブルの削除に失敗しました(#{e.to_s})。"
	end
#
# テーブルの作成(engine = innodbによるストレージエンジンの
#                指定はMySQL依存機能)
#
	begin
		sql = <<SQL
			create table member (
				id INT PRIMARY KEY,
				name VARCHAR(50),
				job VARCHAR(50)
			) engine = innodb
SQL
		dbh.do(sql)
		puts "テーブルの作成に成功しました。"
	rescue => e
		puts "テーブルの作成に失敗しました(#{e.to_s})。"
	end
#
# わざと2重にテーブルを作成してみる
#
	begin
		sql = <<SQL
			create table member (
				id INT PRIMARY KEY,
				name VARCHAR(50),
				job VARCHAR(50)
			)
SQL
		dbh.do(sql)
		puts "テーブルの作成に成功しました(2)。"
	rescue => e
		puts "テーブルの作成に失敗しました(2)(#{e.to_s})。"
	end
#
# インデックスの作成
#
	sql = <<SQL
		create index i_member_name on member(name)
SQL
	dbh.do(sql)
	puts "インデックスの作成に成功しました。"
}
#
# トランザクション(2)
#
dbh.transaction {|dbh|
#
# データの追加
#
	sql = <<SQL
		insert into member (id, name, job) values (?, ?, ?)
SQL
	sth = dbh.prepare(sql)
	sth.execute(1, '伊藤 太郎', 'サラリーマン')
	puts "インサートに成功しました。"
	sth.execute(2, '山田 太郎', '野球選手')
	puts "インサートに成功しました。"
	sth.execute(3, '山田 花子', 'タレント')
	puts "インサートに成功しました。"
#
# わざと2重キーで登録してみる
#
	begin
		sth.execute(3, '山田 花子', 'タレント')
		puts "インサートに成功しました。"
	rescue => e
		puts "インサートに失敗しました(#{e.to_s})。"
	end
	sth.finish
}
#
# データの検索
#
sql = <<SQL
	select * from member where id >= ?
SQL
sth = dbh.prepare(sql)
sth.execute(1)
while (row = sth.fetch)
	puts "セレクトに成功しました(id=#{row['id']})(name=#{row['name']})(job=#{row['job']})"
end
sth.finish
#
# トランザクション(3)
#
dbh.transaction {|dbh|
#
# データの更新
#
	sql = <<SQL
		update member set job = ? where name = ?
SQL
	sth = dbh.prepare(sql)
	sth.execute('裁判官', '山田 太郎')
	puts ("アップデートに成功しました。")
	sth.finish
}
#
# 更新結果の確認
#
sql = <<SQL
	select * from member where name = ?
SQL
sth = dbh.prepare(sql)
sth.execute('山田 太郎')
while (row = sth.fetch)
	puts "アップデートの確認(id=#{row['id']})(name=#{row['name']})(job=#{row['job']})"
end
sth.finish
#
# トランザクション(4)
#
dbh.transaction {|dbh|
#
# データの削除
#
	sql = <<SQL
		delete from member where name like ?
SQL
	sth = dbh.prepare(sql)
	sth.execute('山田%')
	puts ("デリートに成功しました。")
	sth.finish
}
#
# 削除の確認
#
sql = <<SQL
	select * from member
SQL
sth = dbh.prepare(sql)
sth.execute()
while (row = sth.fetch)
	puts "デリートの確認(id=#{row['id']})(name=#{row['name']})(job=#{row['job']})"
end
sth.finish
#
# メタデータの取得
#
sql = <<SQL
	select * from member
SQL
sth = dbh.prepare(sql)
sth.execute()
puts "メタデータ カラム数=#{sth.column_names.size}"
print "メタデータ カラム名="
sth.column_names.each {|name|
	print "#{name}\t"
}
puts ""
#
sth.column_info.each_with_index {|info, i|
        print "項番 = #{i} / "
        print "カラム名 = #{info.name} / "
        print "精度 = #{info.precision} / "
        print "スケール = #{info.scale}\n"
}
sth.finish
#
# (手動で)のコミット(またはロールバック)の実行
#
#dbh.rollback
#puts "ロールバックしました。"
dbh.commit
puts "コミットしました。"
#
# データベースからの切断
#
dbh.disconnect
puts("データベース(dbitestdb)から切断しました。")

実行結果

データベース(dbitestdb)に接続しました。
日本語文字コードをujisに設定しました(MySQL依存設定)。
自動コミット停止しました(トランザクションの開始)。
テーブルの削除に成功しました。
テーブルの作成に成功しました。
テーブルの作成に失敗しました(2)(Table 'member' already exists)。
インデックスの作成に成功しました。
インサートに成功しました。
インサートに成功しました。
インサートに成功しました。
インサートに失敗しました(Duplicate entry '3' for key 1)。
セレクトに成功しました(id=1)(name=伊藤 太郎)(job=サラリーマン)
セレクトに成功しました(id=2)(name=山田 太郎)(job=野球選手)
セレクトに成功しました(id=3)(name=山田 花子)(job=タレント)
アップデートに成功しました。
アップデートの確認(id=2)(name=山田 太郎)(job=裁判官)
デリートに成功しました。
デリートの確認(id=1)(name=伊藤 太郎)(job=サラリーマン)
メタデータ カラム数=3
メタデータ カラム名=id  name    job
項番 = 0 / カラム名 = id / 精度 = 11 / スケール = 0
項番 = 1 / カラム名 = name / 精度 = 150 / スケール = 0
項番 = 2 / カラム名 = job / 精度 = 150 / スケール = 0
コミットしました。
データベース(dbitestdb)から切断しました。

_ googleearth on Libretto U100(Slackware-12.2)

googleearthを入れてみた。十分な速度で動いてくれた。ただし、日本語メニューが化けている。

どうやらパッケージに同梱されている libQt*.so.4 が国際化対応でビルドされた物ではないようだ。そこで qt-x11-opensource-src-4.5.2.tar.gzを取得して ./configure && make && make install でインストールし、 /etc/ld.so.conf に /usr/local/Trolltech/Qt-4.5.2/lib を追加して ldconfig した後、念のために ~/google-earth/配下にある、

$ ls -al google-earth/libQt*
-rwxr-xr-x 1 m-ito m-ito 2244156 2009-07-09 20:38 google-earth/libQtCore.so.4
-rwxr-xr-x 1 m-ito m-ito 7305864 2009-07-09 20:38 google-earth/libQtGui.so.4
-rwxr-xr-x 1 m-ito m-ito  774340 2009-07-09 20:38 google-earth/libQtNetwork.so.4
-rwxr-xr-x 1 m-ito m-ito 7265852 2009-07-09 20:38 google-earth/libQtWebKit.so.4

を削除するなり、リネームするなりして参照されないようにする。

これで無事、日本語メニューも出るようになった。


2009年07月14日 Kernel Version UP 2.6.27.7 to 2.6.29.6 on Slackware-12.2 [長年日記]

_ Kernel Version UP 2.6.27.7 to 2.6.29.6 on Slackware-12.2

Libretto U100(Slackware-12.2)の無線LAN(ath5k Atheros AR2414)の調子があまり良くない。接続ができないわけでは無いけれども、速度が異常に遅い。/var/log/syslogに以下のメッセージが連続して記録されている。

Jul 13 04:55:31 lib190 kernel: ath5k phy0: noise floor calibration timeout (2462MHz)

上記のメッセージ(kernel: ath5k phy0: noise floor calibration timeout)で検索してみると、同様の報告が結構あって、カーネルのバージョンをアップすれば改善する様子。

そこで現行の 2.6.27.7 から 2.6.29.6 へバージョンアップすることにする。現時点での最新カーネルは 2.6.30.1 なのだが、Slackware-currentが 2.6.29.5 だったので、同系列の最新版を採用することにした。コンフィグ(config-huge-smp-2.6.29.5-smp)もSlackware-currentのものを利用できるし、安心。

# cd /usr/src
# rm linux
# tar xvjf linux-2.6.29.6.tar.bz2
# ln -s linux-2.6.29.6 linux
# cd linux
# make mrproper
# cp /anywhere/config-huge-smp-2.6.29.5-smp .config
# make oldconfig
# make menuconfig  <-- CPU TYPE を Pentium-M に変更
# make
# make modules_install
# make install

Cahngesを確認すると、e2fsprogs-1.41.4以上を求められているが、Slackware-12.2のは1.41.3だったので、これもバージョンアップする。Slackware-currente2fsprogsのビルドスクリプトを参考にして、

# tar xvzf  e2fsprogs-1.41.8.tar.gz
# cd e2fsprogs-1.41.8
# VERSION=1.41.8
# ./configure \
      --prefix=/usr \
      --libdir=/lib \
      --bindir=/usr/bin \
      --includedir=/usr/include \
      --datadir=/usr/share \
      --mandir=/usr/man \
      --infodir=/usr/info \
      --docdir=/usr/doc/e2fsprogs-$VERSION \
      --enable-elf-shlibs \
      --enable-dynamic-e2fsck \
      --enable-libblkid \
      --disable-uuidd
# make
# make install
# make install-libs

以上で、カーネルバージョンアップ+αの作業完了。あとはこれで無線LANが安定してくれれば...。

_ X.orgで日本語フォントが中国っぽくなる件

# cd /etc/fonts/conf.d
# mv 44-wqy-zenhei.conf 44-wqy-zenhei.conf.REMOVED

にて解決。


2009年07月19日 libretto100(myh.no-ip.org server) harddisk crash! [長年日記]

_ libretto100(myh.no-ip.org server) harddisk crash!

4月にディスク交換したmyh.no-ip.orgのサーバであったが、見事にディスククラッシュ。

前日に異音を発したのでとりあえず再起動を行い、異音が消えたため即座にバックアップを取得し、そのまま継続運用していた。

翌日、仕事から帰ってみるとフリーズ状態。再起動して稼働することは確認するも、その後出かける用事があったので念のために(発熱で火災でも起こすと困るので)シャットダウンして出かける。

帰宅して電源入れるも、ハードディスクが異音を起てて起動せず。完全にクラッシュ状態となる。

はぁ〜...

予備のハードディスクにバックアップから戻し、復旧。

_ 教訓:ヤフオクの(中古)ハードディスクは信用できない。


2009年07月25日 firefox-3.0.12, firefox-3.5.1 on Slackware-12.2 [長年日記]

_ firefox-3.0.12, firefox-3.5.1 on Slackware-12.2

.mozconfig

. $topsrcdir/browser/config/mozconfig
ac_add_options --disable-debug
ac_add_options --enable-optimize
ac_add_options --enable-default-toolkit=cairo-gtk2

build

nice make -f client.mk build
nice make package

2009年07月30日 MySQL-5.x 儂(わし)的解釈によるメモ(運用編) [長年日記]

_ MySQL-5.x 儂(わし)的解釈によるメモ(運用編)

Slackware-12.xに標準でインストールされるMySQL-5.xをそのまま運用する際に 最低限必要と思われる知識に関するメモ。いろんなページの切り貼り。

Java儂(わし)的解釈によるメモ(JDBC + MySQL編)と若干かぶってるのは御勘弁を。

前提条件

  • MySQLの管理者 root
  • MySQLの一般ユーザ兼管理者 m-ito

データベース領域の初期化

mysqldを起動するに当たって、一度だけ実行する必要がある。

# mysql_install_db --user=mysql

mysqld起動スクリプトの修正

ネットワーク越しにアクセス(JDBC経由も含む)するために起動オプションを修正する (/etc/rc.d/rc.mysqld)。

#SKIP="--skip-networking"  <-- コメントアウト

MySQLコンフィグファイル設定

デフォルト文字コード、デフォルトストレージエンジンの設定。

標準のストレージエンジンであるMyISAMは速度は早いが、トランザクションが サポートされていない。非標準のストレージエンジンであるInnoDBMyISAMに 比べると速度が劣るがトランザクションをサポートする。

汎用機畑で育った私としてはトランザクションが無い(すなわちcommitrollbackが無い)のは信じられないので、デフォルトのストレージエンジンを InnoDBに変更する。また、クライアント、サーバともにデフォルトの文字コー ドをujisとする。最近はutf8が主流になりつつあるそうですが...。

 # cp /etc/my-small.conf /etc/my.cnf
 # vi /etc/my.cnf
 [client]
 ##default-character-set = utf8
 default-character-set = ujis

 [mysqld]
 ##default-character-set = utf8
 default-character-set = ujis
 default-storage-engine=innodb

mysqld起動

# chmod +x /etc/rc.d/rc.mysqld; reboot

MySQL管理者(root)のパスワード設定

$ mysqladmin -u root password ROOT-PASSWORD

データベース(testdb)の作成

$ mysql -u root -p
Enter password: XXXXXXXXXXXXX <-- ROOT-PASSWORDを入力する
mysql> create database testdb character set ujis;
mysql> quit

一般ユーザ(m-ito)を作成

$ mysql -u root -p
Enter password: XXXXXXXXXXXXX <-- ROOT-PASSWORDを入力する
mysql> create user 'm-ito'@'localhost' identified by 'USER-PASSWORD';
mysql> quit

一般ユーザ(m-ito)にデータベースへのアクセス権を設定

$ mysql -u root -p testdb
Enter password: XXXXXXXXXXXXX <-- ROOT-PASSWORDを入力する
mysql> grant all on testdb.* to 'm-ito'@'localhost' identified by 'USER-PASSWORD';
mysql> quit

一般ユーザ用MySQLコンフィグファイル設定

パスワードの設定とデフォルト文字コードの設定。このあたりは必要に応じ て...。

$ cp /etc/my-small.conf ~m-ito/.my.cnf
$ chmod 600 ~m-ito/.my.cnf
$ vi ~m-ito/.my.cnf
[client]
password = USER-PASSWORD
##default-character-set = utf8
default-character-set = ujis

データベース、テーブル情報表示

$ mysqlshow -u m-ito -p testdb HogeTable

データベースのダンプ出力

$ msql -u root -p testdb
LOCK TABLES HogeTable READ;
CTRL-Z
$ mysqldump -u m-ito -p testdb HogeTable
$ mysqldump -u m-ito -p --databases testdb
$ mysqldump -u m-ito -p --all-databases
$ fg
UNLOCK TABLES;

ユーザ管理

$ mysql -u root -p
権限の種類
  • DELETE : DELETE構文を実行できる権限。
  • INSERT : INSERT構文を実行できる権限。
  • SELECT : SELECT構文を実行できる権限。
  • UPDATE : UPDATE構文を実行できる権限。
  • INDEX : インデックスの作成と削除が行える権限。
  • REFERENCES : テーブルのリファレンスが参照できる権限。
  • USAGE : すべての権限がない。
管理者の追加
GRANT ALL ON *.* TO 'm-ito'@'%' IDENTIFIED BY 'USER-PASSWORD' WITH GRANT OPTION;
GRANT ALL ON *.* TO 'm-ito'@'localhost' IDENTIFIED BY 'USER-PASSWORD' WITH GRANT OPTION;
FLUSH PRIVILEGES;
一般ユーザの追加
GRANT SELECT,INSERT,UPDATE,DELETE ON testdb.* TO 'm-ito'@'localhost' IDENTIFIED BY 'USER-PASSWORD';
FLUSH PRIVILEGES;
ユーザ権限の削除
REVOKE ALL ON testdb.* FROM 'm-ito';
FLUSH PRIVILEGES;
ユーザの削除

REVOKEにて全ての権限を削除後

DROP USER 'm-ito';
FLUSH PRIVILEGES;
ユーザの権限確認
SELECT * FROM mysql.user WHERE User='m-ito';

データベースの削除

mysql -u root -p
DROP DATABASE testdb;

パスワードの設定

mysql -u root -p
SET PASSWORD FOR 'm-ito'@'%' = PASSWORD('USER-PASSWORD');

CSVファイルの取り込み

mysql -u root -p
LOCK TABLES HogeTable WRITE;
LOAD DATA INFILE "Hoge.csv" INTO TABLE HogeTable FIELDS TERMINATED BY ',' ENCLOSED BY '"';
UNLOCK TABLES;
  • フィールド区切り文字のデフォルトは「タブ」。
  • 文字列囲み文字のデフォルトは「無し」。

CSVファイルへの書き出し

mysql -u root -p
LOCK TABLES HogeTable READ;
SELECT * FROM HogeTable INTO OUTFILE "Hoge.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"';
UNLOCK TABLES;
  • フィールド区切り文字のデフォルトは「タブ」。
  • 文字列囲み文字のデフォルトは「無し」。

_ BIND 9の脆弱性について

BIND 9にてDynamic DNS機能に関して脆弱性が報告されている。DoSの対称になってしまうとのこと。

JVNVU#725188 ISC BIND 9 におけるサービス運用妨害 (DoS) の脆弱性

早速、libretto100(myh.no-ip.org)のbindもバージョンアップ。

bind-9.4.3-P3


2009年07月31日 Java儂(わし)的解釈によるメモ(JDBC + Microsoft SQL Server 2005 Express Edition編) [長年日記]

_ Java儂(わし)的解釈によるメモ(JDBC + Microsoft SQL Server 2005 Express Edition編)

Windowsの事も知らんぷりできない状況になりつつある中、Microsoft SQL Server 2005 Express Editionという無償で使える MS SQL Serverが有る事を知り、早速試してみた。

基本的にはJava儂(わし)的解釈によるメモ(JDBC + MySQL編)の内容と大差無いが、やはり多少の方言と言うか違いは存在していた。

Windows機(IP=192.168.0.1)側にインストールする物

以上でサーバが起動する。

  • sqlcmd.exe(Windows側ツール)

sqlcmd.exeはWindows側でデータベースにアクセスするためのクライアント(コマンドライン版)。

インスタンス名はSQLExpressに固定。

ところでインスタンスてなんじゃという話だが、1個のインスタンスが1個のリスナーポートに対応していて、つまりこれが1個のデータベース(この中に多数のテーブルを抱える)サーバプロセスということらしい。(データベースはCREATE DATABASE testdb で作成する...)

sqlcmd -?
  ヘルプ表示
sqlcmd -U sa -P SA-PASSWORD -S localhost\SQLExpress
  1> SQL命令文
  2> GO
  3> EXIT
sqlcmd -U sa -P SA-PASSWORD -S localhost\SQLExpress -s "," -W -i Hoge.sql

クライアント側(Linux or Windows)にインストールする物

Microsoft SQL Server JDBC Driver 2.0内のsqljdbc4.jarCLASSPATHに追加するか、実行時に

java -cp /somewhere/sqljdbc4.jar HogeHoge

の様に指定する。

サンプルプログラム

//
// 「jdbc mssql」テスト
//
// compile : javac -encoding utf-8 jdbc_mssql.java
// run     : java -cp .:sqljdbc4.jar jdbc_mssql
//
//import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class jdbc_mssql {

	static Connection conn = null;
	static Statement stmt = null;
	static PreparedStatement pstmt = null;
	static ResultSet rs = null;
	static ResultSetMetaData rsmd = null;

	public static void main(String[] args) {
		try {
//
// JDBC for MS SQL Serverのロード
//
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
			System.out.println("JDBCドライバをロードしました。");
//
// データベースへの接続
//
//			String url = "jdbc:sqlserver://192.168.0.1:1433";
//			conn = DriverManager.getConnection(url, "sa", "SA-PASSWORD");
			String url = "jdbc:sqlserver://192.168.0.1:1433;databaseName=testdb;user=sa;password=SA-PASSWORD;";
			conn = DriverManager.getConnection(url);
			System.out.println("jdbc:sqlserver://192.168.0.1:1433に接続しました。");
//
// 自動コミット有効
//
//   自動コミットを有効にしないと create index で、テーブル member を見つけられずに
//   例外が発生する。MS SQLServer特有の現象か?。
//
			conn.setAutoCommit(true);
			System.out.println("自動コミットをONにしました。");
//
// SQLステートメントオブジェクト生成
//
			stmt = conn.createStatement();
//
// テーブルの削除
//
			try {
				stmt.executeUpdate("drop table member");
				System.out.println("テーブル member を削除しました。");
			} catch(Exception e){
				System.out.println("テーブル member を削除できませんでした(" + e.getMessage() + ")");
			}
//
// テーブルの作成
//
			stmt.executeUpdate(
				"create table member (" +
					"id INT PRIMARY KEY," +
					"name VARCHAR(50)," +
					"job VARCHAR(50)" +
				")"
			);
			System.out.println("テーブル member を作成しました。");
//
// わざと2重にテーブル作成してみる
//
			try {
				stmt.executeUpdate(
					"create table member (" +
						"id INT PRIMARY KEY," +
						"name VARCHAR(50)," +
						"job VARCHAR(50)" +
					")"
				);
				System.out.println("テーブル member を作成しました(2)。");
			} catch(Exception e){
				System.out.println("テーブル member を作成できませんでした(2)(" + e.getMessage() + ")");
			}
//
// 2次インデックス作成
//
			stmt.executeUpdate("create index i_member_name on member(name)");
			System.out.println("インデックスを作成しました。");
//
// 自動コミット無効
//
			conn.setAutoCommit(false);
			System.out.println("自動コミットをOFFにしました(トランザクション開始)。");
//
// タプルの追加
//
			try {
				pstmt = conn.prepareStatement("insert into member (id, name, job) values (?, ?, ?)");
//
// 1件目
//
				pstmt.setInt(1, 1);
				pstmt.setString(2, "伊藤 太郎");
				pstmt.setString(3, "サラリーマン");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// 2件目
//
				pstmt.setInt(1, 2);
				pstmt.setString(2, "山田 太郎");
				pstmt.setString(3, "野球選手");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// 3件目
//
				pstmt.setInt(1, 3);
				pstmt.setString(2, "山田 花子");
				pstmt.setString(3, "タレント");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
//
// わざと3件目をもう一度追加してみる
//
				pstmt.setInt(1, 3);
				pstmt.setString(2, "山田 花子");
				pstmt.setString(3, "タレント");
				pstmt.executeUpdate();
				System.out.println("インサートしました。");
			} catch (Exception e) {
				System.out.println("インサートできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの検索
//
			try {
//
// クエリの実行
//
				pstmt = conn.prepareStatement("select * from member where id >= ?");
				pstmt.setInt(1, 1);
				rs = pstmt.executeQuery();
//
// 1件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// 2件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// 3件目の取り出し
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
//
// わざと存在しない4件目を取り出してみる
//
				rs.next();
				System.out.println("セレクトしました(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
			} catch (Exception e) {
				System.out.println("セレクトできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの更新
//
			try {
//
// 更新ステートメント実行
//
				pstmt = conn.prepareStatement("update member set job = ? where name = ?");
				pstmt.setString(1, "裁判官");
				pstmt.setString(2, "山田 太郎");
				pstmt.executeUpdate();
				System.out.println("アップデートしました。");
//
// 更新結果を取り出すクエリの実行
//
				pstmt = conn.prepareStatement("select * from member where name = ?");
				pstmt.setString(1, "山田 太郎");
				rs = pstmt.executeQuery();
//
// クエリ結果の取り出し
//
				rs.next();
				System.out.println("アップデート結果(id=" +
					rs.getInt("id") + ")(name=" +
					rs.getString("name") + ")(job=" +
					rs.getString("job") + ")。");
			} catch (Exception e) {
				System.out.println("アップデートできませんでした(" + e.getMessage() + ")");
			}
//
// タプルの削除
//
			try {
//
// 削除ステートメント実行
//
				pstmt = conn.prepareStatement("delete from member where name like ?");
				pstmt.setString(1, "山田%");
				pstmt.executeUpdate();
				System.out.println("デリートしました(" + pstmt.getUpdateCount() + "件)。");
//
// 削除後の状態の検索クエリ実行
//
				pstmt = conn.prepareStatement("select * from member");
				rs = pstmt.executeQuery();
//
// クエリ結果の取り出し
//
				while (rs.next()){
					System.out.println("デリート結果(id=" +
						rs.getInt("id") + ")(name=" +
						rs.getString("name") + ")(job=" +
						rs.getString("job") + ")。");
				}
			} catch (Exception e) {
				System.out.println("デリートできませんでした(" + e.getMessage() + ")");
			}
//
// メタデータの取得
//
			try {
//
// メタデータの取得
//
				rsmd = rs.getMetaData();
//
// カラム数の取得
//
				int numberOfColumns = rsmd.getColumnCount();
				System.out.print("メタデータを取得しました(");
				for (int i = 1; i <= numberOfColumns; i++) {
//
// カラム名称の取得
//
					String name = rsmd.getColumnName (i);
					System.out.print(name + "\t");
				}
				System.out.println(")。");
			} catch (Exception e) {
				System.out.println("メタデータを取得できませんでした(" + e.getMessage() + ")");
			}
//
// コミット(トランザクションの反映)
//
			try {
				conn.commit();
				System.out.println("コミットしました。");
			} catch (Exception e) {
				System.out.println("コミットできませんでした(" + e.getMessage() + ")");
			}
		} catch (SQLException e) {
			System.out.println("SQLException: " + e.getMessage());
			System.out.println("SQLState: " + e.getSQLState());
			System.out.println("VendorError: " + e.getErrorCode());
//
// ロールバック(トランザクションの破棄)
//
			try {
				conn.rollback();
			} catch(Exception e2){
				System.out.println(e2.getMessage());
			}
		} catch(Exception e){
			System.out.println(e.getMessage());
//
// ロールバック(トランザクションの破棄)
//
			try {
				conn.rollback();
			} catch(Exception e2){
				System.out.println(e2.getMessage());
			}
		}

		try {
//
// 検索クエリの結果セットオブジェクトを破棄
//
			rs.close();
//
// SQLステートメントオブジェクトを破棄
//
			stmt.close();
			pstmt.close();
//
// データベースからの切断
//
			conn.close();
		} catch(Exception e){
			System.out.println(e.getMessage());
		}
		System.out.println("mssqlserverから切断しました。");

	}
}

実行結果

JDBCドライバをロードしました。
jdbc:sqlserver://192.168.0.1:1433に接続しました。
自動コミットをONにしました。
テーブル member を削除しました。
テーブル member を作成しました。
テーブル member を作成できませんでした(2)(データベースに 'member' という名前のオブジェクトが既に存在します。)
インデックスを作成しました。
自動コミットをOFFにしました(トランザクション開始)。
インサートしました。
インサートしました。
インサートしました。
インサートできませんでした(制約 'PK__member__2E3BD7D3' の PRIMARY KEY 違反。オブジェクト 'dbo.member' には重複したキーを挿入できません。)
セレクトしました(id=1)(name=伊藤 太郎)(job=サラリーマン)。
セレクトしました(id=2)(name=山田 太郎)(job=野球選手)。
セレクトしました(id=3)(name=山田 花子)(job=タレント)。
セレクトできませんでした(ResultSet に現在の行がありません。)
アップデートしました。
アップデート結果(id=2)(name=山田 太郎)(job=裁判官)。
デリートしました(2件)。
デリート結果(id=1)(name=伊藤 太郎)(job=サラリーマン)。
メタデータを取得しました(id     name    job     )。
コミットしました。
mssqlserverから切断しました。

追記

  • stmt.executeUpdate(INSERT|DELETE|UPDATE) の戻り値は更新されたタプル数
  • stmt.executeUpdate(上記以外の更新系SQL) の戻り値は 0
  • エラー発生時は SQLExceptin 発生。getSQLState()にてエラーコードを取得できる。

MySQLとの違い

最初からAutoCommit=falseにしていると、create indexでテーブルが見つけられずに例外が発生した。create tableの直後に明示的にcommitを発行してもダメで、結局create indexまではAutoCommit=trueで実行し、それ以降をAutoCommit=falseで実行することで(無理矢理)解決した。

ショック

一応、サーバをSQL Server 2008 Express with Advanced Servicesに変えても、上記のサンプルは動いた。