2009年07月03日 DVD on Libretto U100 [長年日記]
_ DVD on Libretto U100
せっかくwritableなDVDドライブが付いているので、Slackware-12.2でDVD 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^)/。
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は速度は早いが、トランザクションがサポートされていない。非標準のストレージエンジンであるInnoDBはMyISAMに比べると速度が劣るがトランザクションをサポートする。
汎用機畑で育った私としてはトランザクションが無い(すなわち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(情報のみ)
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-currentのe2fsprogsのビルドスクリプトを参考にして、
# 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は速度は早いが、トランザクションが サポートされていない。非標準のストレージエンジンであるInnoDBはMyISAMに 比べると速度が劣るがトランザクションをサポートする。
汎用機畑で育った私としてはトランザクションが無い(すなわちcommit、 rollbackが無い)のは信じられないので、デフォルトのストレージエンジンを 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
権限の種類
- ALL : すべての権限。
- ALTER : ALTER TABLE構文が実行できる権限。
- CREATE : データベースとテーブルの作成が行える権限。
- DROP : データベースとテーブルの削除が行える権限。
- FILE : LOAD DATA構文とSELECT 〜 INTO OUTFILE構文を実行できる権限。
- PROCESS : mysqladminコマンドのprocesslistとkill命令を実行できる権限。
- RELOAD : mysqladminコマンドのreload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables命令を実行できる権限。
- SHUTDOWN : mysqladminコマンドのshutdown命令を実行できる権限。
- 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もバージョンアップ。
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)側にインストールする物
- Microsoft .NET Framework Version 2.0 再頒布可能パッケージ (x86)
- MS SQL Server 2005 Express edition インストールのポイント
- 「機能の選択」において、とりあえず全コンポーネントを選択する。
- 「認証モード」において、混合モードを選択する。また管理者(sa)のパスワードも設定する。
- インストール完了後、スタートメニューより
- 「プログラム」->「Microsoft SQL Server 2005」->「構成ツール」->「SQL Server Configuration Manager」を起動し
- 「SQL Server 2005 ネットワークの構成」->「SQLEXPRESSのプロトコル」->「TCP/IP」->「プロパティ」->「IPアドレス」->「TCPポート」に「1433」を設定する。その後、上記の「TCP/IP」を「有効化」する。
- 「SQL Server 2005 のサービス」->「SQL Server(SQLEXPRESS)」->「再起動」を行う。
以上でサーバが起動する。
- 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.jarをCLASSPATHに追加するか、実行時に
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で実行することで(無理矢理)解決した。
ショック
- Microsoft SQL Server 2005 Express Edition with Advanced Services(Express Edition + Management Studio Express)というのが有ったんだね。
- さらに新しいMicrosoft SQL Server 2008 Expressというのも有ったんだね...。
一応、サーバをSQL Server 2008 Express with Advanced Servicesに変えても、上記のサンプルは動いた。