「unixODBC+FreeTDS+DBD::ODBCでSQL Serverに接続する」Part2
※前回の続きです。
設定ファイルをいじる
4.odbc.iniの編集
# vim /usr/local/etc/odbc.ini -- [ODBC Data Sources] <span style="color:#FF0000;">freetds = FreeTDS ODBC Driver [freetds] Driver = /usr/local/lib/libtdsodbc.so Description = Microsoft SQL Server Servername = mssql Database = dbname
5.freetds.confの編集
# vim /usr/local/etc/freetds.conf -- [mssql] host = 192.168.XXX.XXX port = 1433 tds version = 8.0 charset = sjis client charset = UTF-8 language = english
補足
host←SQL ServerをインストールしたホストのIPアドレスにすること
client charset←データに日本語を使わないなら「UTF-8」にしても良い
language←japaneseにするとエラーメッセージなどが日本語で表示されるが、
環境によって文字化けする場合もあるのでenglishがお勧め。
【重要】
odbc.iniのServernameとfreetds.confのセクションをあわせます。
■接続テスト
# tsql -H 192.168.xxxx.xxx -p 1433 -U admin -P hogehoge locale is "ja_JP.UTF-8" locale charset is "UTF-8" 1> use test_db 2> go 1> select count(*) from hogehoge 2>go 1>exit
o(・∇・o)(o・∇・)o ヤッタ!つながった!!
これでDBIとfreetdsを使った接続は成功です!!
DBD::ODBC編
DBD::ODBCのインストール
#perl -MCPAN -e shell cpan> install DBD::ODBC --20:01:22-- ftp://ftp.perl.org/pub/CPAN/authors/id/M/MJ/MJEVANS/DBD-ODBC-1.15.tar.gz (試行: 9) => `-' ftp.perl.org|163.143.1.21|:21 に接続しています... 接続しました。 anonymous としてログインしています... サーバの応答にエラーがあるので、接続を終了します。 再試行しています。
あれ?失敗
■接続先URLを追加して実行(以下でいけるらしい)
cpan> o conf cpan> o conf urllist push 追加したい url名 cpan> o conf commit
◎追加するURLは
「http://search.cpan.org/CPAN/authors/id/M/MJ/MJEVANS/DBD-ODBC-1.15.tar.gz」
cpan使っても一回install
#perl -MCPAN -e shell cpan> install DBD::ODBC
◎警告はわさわさ出たけど入ったから次へ。
7.接続テストスクリプト作成
# vim odbc.pl -- #!/usr/bin/perl use strict; use DBI; use Data::Dumper; my $dbh = DBI->connect('dbi:ODBC:freetds', 'username', 'passwd') or die $!; my $sth = $dbh->prepare("select top 10 * from test_table") or die $dbh->errstr; $sth->execute or die $dbh->errstr; while (my $arrayref = $sth->fetchrow_arrayref) { print Dumper $arrayref; } $sth->finish; $dbh->disconnect;
8.接続テストスクリプト実行
# perl odbc.pl DBI connect('freetds','username',...) failed: [unixODBC][Driver Manager]Data source name not found, and no default driver specified (SQL-IM002) at odbc.pl line 7 Died at odbc.pl line 7.
エラー
データソースの設定がミスってますって怒られています。
ここからしばらくデバッグの経緯です。(省きたい人はすっとばしてください。)
■ドライバの一覧を確認してみます
odbc.pl に以下の記述を追加して実行
my @ary = DBI->available_drivers; print Dumper(\@ary); ------実行結果------- #perl odbc.pl $VAR1 = [ 'DBM', 'ExampleP', 'File', 'ODBC', ←いました。 'Pg', 'Proxy', 'Sponge' ];
■ODBCの一覧を見てみます
my @ary = DBI->data_sources('ODBC'); print Dumper(\@ary); ------実行結果------- #perl odbc.pl $VAR1 = [];
からっぽです。
■今どの設定ファイルみてるのかを調べる
#odbcinst -j unixODBC 2.2.11 DRIVERS............: /etc/odbcinst.ini SYSTEM DATA SOURCES: /etc/odbc.ini USER DATA SOURCES..: /root/.odbc.ini
↑こんな結果です。
どうやら「/etc/odbc.ini」を見ているようです。
設定をこちらに書いてみます。
■再実行結果
#perl odbc.pl $VAR1 = [ 'dbi:ODBC:freetds' ];
とれました。
■再度perl実行
# perl odbc.pl
できたーーーーー!!!
・゚・(つД`)・゚・値がとれましたー!!
↑ここまではasciiだけのテーブルが対象でした。
こっからは日本語の出力です。
■SQLを日本語の入っているテーブルに変更して実行
my $sth = $dbh->prepare("select top 10 * from test_table<span style="color:#FF0000;">_jp</span>") or die $dbh->errstr;
何か途中で落ちる。。。
■カラムを指定して実行
my $sth = $dbh->prepare("select top 10 id,name from test_table_jp") or die $dbh->errstr;
無事日本語も表示されました。
(-ω-???????
どうやら型の中に「varchar(max)」があると落ちるようです。
http://www.mail-archive.com/dbi-users@perl.org/msg26962.html
↑パッチらしきものを発見
■diffにそってソースを修正後makeし直します。
vim /root/.cpan/build/DBD-ODBC-1.15/dbdimp.c make clean perl Makefile.PL make make test make install
結果は同じでした。。。
■デバッグに入ります。
まずはエラーを拾います。
http://www.rfs.jp/sb/perl/dbi/03.html
↑ここに「DBI->trace」こんなん載ってた。
デバッグレベルを変更します。
my $dbh = DBI->connect('dbi:ODBC:freetds', 'sa', '1ndivision',{PrintError=>0,AutoCommit=>0}) or die $!; $dbh->trace(3);
↑デバッグ最強レベルまで上げる。
その結果。エラー文のような物がはかれました。
怪しい部分だけ抜き出します。
now using col 1: type = CHAR (1), len = 20, display size = 21, prec = 20, scale = 0 now using col 2: type = VARCHAR (12), len = 800, display size = 801, prec = 800, scale = 0 now using col 3: type = LONG VARCHAR (-1), len = 258048, display size = 81, prec = 258048, scale = 0
col3がvarchar(max)部分になります。
display size が他のカラムに比べて少なすぎます。
ほかのカラムはlen+1 サイズになってるのに
varchar(max)のカラムはやたらと少ないです。
C言語経験者に頼る。。。。orz
「dbdimp.c」をデバッグする
case文にデバッグ入れ込んでみるとvarchar(max)の場合
「LONG VARCHAR」として判定されている事が判明!!
以下の関数部分を修正。
#vim /root/.cpan/build/DBD-ODBC-1.15/dbdimp.c dbd_describe(h, imp_sth, more)関数の下部分のcase文の中にif文追加 case SQL_LONGVARCHAR: if (fbh->ColDef <= 0) { fbh->ColDisplaySize = DBIc_LongReadLen(imp_sth)+1; } break;
修正しました。
#make install #perl odbc.pl
now using col 3: type = LONG VARCHAR (-1), len = 258048, display size = 258049, prec = 258048, scale = 0
出ました!!!
fetchできちんと値が取れました!!!!
(^-^;)とりあえず出たので完了とします。。。