2007.05.23

SQLServer2005 tips

ここ1ヶ月ほど遠征して SQLServer2005 + AD, Exchangeと格闘しておりました。
その成果をいくつかメモしておきます。


1.SQLServerリンクサーバーで参照する Oracleデータベースのテーブルは全て大文字で記述する必要がある。
  SELECT * FROM ORACLE..SCOTT.EMP


2.SQLServerリンクサーバーで参照する Oracleデータベースに日付型で 1753/01/01 以前が入っているとリンク時にSQLServerの日付型に変換できず落ちる。
WHERE条件にも直接日付項目の絞込みを書けないので他の条件で落とす必要がある。
(対象外レコードマスタを作るとか)


3. Char(2)のコード項目に1文字のみ入っている場合って、こういうものか?
  Declare @s1 char(2)
  Set @s1='@'
  print Len(@s1) -- 1が表示される(?)
  print @s1 + @s1 -- 間にスペースがつく(許容できる)
  print Len(@s1+@s1) -- 3が表示される(?)

  Declare @s2 varchar(2)
  Set @s2='@ '
  print Len(@s2) -- 1が表示される(??)
  print @s1 + @s2 -- 間にスペースがつく(当たり前)
  print Len(@s2+@s2) -- 3が表示される(??)


4.BCPで CSVファイル出力する際、フィールドで Nullの項目は bcpの出力では「,,」で作成されるが、
空文字の項目は「, ,」とスペースが勝手に1個入る。bcpの既定はこんな動作か?


5.SQLServerのミラー構成でプリンシパルをリストアする際には、いったんミラーを停止(解除)しておいて、
プリンシパルに(完全バックアップ+ログ)を復元、またミラーにも同じファイルを復元(ログは開いたまま)。
を行ってからミラーを再開しなくいけないようだ。多いなる手間。


6.SQLServerがミラー構成の場合、ストアドはプリンシパルに登録するだけでミラーサーバーにも反映される。
ただし、リンクサーバーの設定や、拡張オプションなどサーバー単位の設定項目は、ミラーサーバーにも事前に設定しておかないといけない。
(ストアドコンパイル時にリンクの先などをチェックしているはずだが、リンクサーバーを設定していないミラーサーバー内でストアドはどういう状態になっているのか?)


7.タイトルを付けて BCP-CSV出力する際、グローバル一時テーブルを作成し、
クラスタ化インデックスの IDENTITY 項目と 文字列を1個持つだけにしたりすることがある。
しかし、どうも出力で使う一時テーブルの名称に、いつもの調子で DB名まで付けていると、以下のようなエラーが出る、ことがある。
  BCP "SELECT s1 FROM DB1.dbo.##TempCsv ORDER BY k1" QyeryOut -T -c

 SQLState = HY000, NativeError = 0 Error = [Microsoft][SQL
 Native Client]サーバーへのコピー中に、ホストファイルの行がスキップされた可能性があります。」

このエラーが出た場合は、必ず1行(タイトル)データがあるはずの場合でも 0バイトのファイルしかできていない。
ただ、動作は極めてアナログで、まったく同じ件数でも症状が出たり出なかったりする。
helpをよく読むと一時テーブルは tempDBにあることが決まっているので DB名を補う必要はないらしい、てのが原因のようだが。
エラー内容が極めて不親切なので、はまると抜け出すのは容易でない。


8.TransactSQL内で TRY-CATCH処理を掛けるようにすると、@@ERRORでの判断ではエラーが取れなくなっっていると思われる。
しかし、処理の最も外側に TRY-CATCHを掛けていると継続して良い警告でもまったく飛ばされることになる。
わざわざ内部に再度 TRY-CATCHを掛けて処理を拾わなくてはいけないところが少々気づきにくいところ。
また致命的な Catchは、多段のストアドの1個手前のストアドでないとキャッチできない気がする。


9.アドホックな外部データの取り込みを行う際に、以下のように書ける。
 SELECT x.* INTO [$ADUser]
  FROM OPENROWSET (
    'Microsoft.Jet.OLEDB.4.0'
   , 'TEXT;HDR=NO;DATABASE=C:\ichikawa@ilovex\■移行用データ\'
   , Users_USR#txt
  ) x -- テキストファイル
 SELECT x.* /* INTO [$Eメール一覧] */
  FROM OPENROWSET (
    'Microsoft.Jet.OLEDB.4.0'
   , 'Excel 8.0;HDR=YES;DATABASE=C:\ichikawa@ilovex\■移行用データ\6_SendMail\Eメール一覧.xls'
   , Sheet1$
  ) x -- Excelファイル

注1)パス名をダブルクォートで囲むとエラーになる。
注2)ヘッダ行の有無は制御可能
注3)フィールドの自動判別は避けられない。型誤りのデータは勝手に Nullに置き換えられる。


おまけ.ADからメールボックスストアと Exchangeで振った複数のメールアドレスを取り出すには
CDO.Person が必要だが、これは Exchangeの管理系ツールを入れただけではインストールされない。
Exchange本体がインストールされたマシンで行わねばならん。

コメント (2)

おつかれさまです。
OPENROWSETでもIMEX=1が効きます。
全部強制的に文字列と判別させて、チェックするのがよいかと
http://support.microsoft.com/kb/194124/ja

コメントありがとうございます。

OPENROWSETで IMEX=1が指定できるのは知ってはいたのですが、
いざ実際設定してみても型の自動認識から抜け出せませんでした。
レジストリをいじって推測に使われる行数を変えてみたりもしたのですが、芳しくなく。

やり方なのか、バージョンの組み合わせなのかが悪かったりしたのでしょうか・・・。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

photo
ichikawa