NotesSQLとMS SQL Serverとを組み合わせてみる

Lotus Domino / Notes (IBM) のデータベースを、Microsoft SQL Server のリンクサーバ機能を利用してアクセスしてみます。難渋しないよう、メモをしておきます。
#実現のきも
- ノーツクライアントのインストールされているOS上にODBCドライバとSQLServerをインストールする場合は、WindowsOS のアーキテクチャが64ビットであっても32ビット版を使います。ノーツクライアントの 64bit 版が現れたら、64ビット版のODBCドライバーとSQLServerが使えるようになるでしょう。
    - Dominoサーバー（64bit版）と同じOSに導入する場合は、ODBCドライバーもSQLServerも64ビット版を使います。

#試してみる
##構成
これは、私が検証した構成です。他の構成でも使えると思います。
<dl>
<dt>ドミノコンピュータ</dt><dd>Windows Server 2008 R2<ul><li>Lotus Domino Server 8.5.2 / 9.0.1 （今回利用するデータの源泉）</ul></dd>
<dt>SQLサーバコンピュータ</dt><dd>Windows Server 2008 R2<ul><li>SQL Server データベース 32ビット版（私は 2014 Express を使用してみました。外部から TCP 接続でログインできるようにしておきます(TCP/IP 有効化とファイアウォール定義)）<li>Lotus Notes クライアント（DominoServer へログインできる状態まで、設定を行っておきます。Basic と Standard はどちらでもよいです）<li>NotesSQL ODBC ドライバ 32ビット版（無償。IBM のサイトからダウンロードできます）</ul></dd>
<dt>クライアント</dt><dd>Windows 7 / Windows 10<ul><li>SQL Sever Management Studio（MSSQLServer へ接続できるようにしておきます）</ul>ここには、ノーツクライアントや NotesSQL ODBC ドライバをインストールする必要はありません。また、こちらが 32bitOS か64bitOS かは無関係です。</dd>
</dl>
##手順
###SQLサーバコンピュータですること
1. OSの環境変数 PATH にノーツ実行ファイル (notes.exe など)のあるパスを登録して、実行パスを通しておきます。
2. Notes SQL Authentication List Manager (Nsql_ALM.exe) なるツールを起動します。
![F1.png](https://qiita-image-store.s3.amazonaws.com/0/100206/e1d20465-37dd-5085-c07f-7ec00f549003.png)
2. Step.1 で、クライアントの notes.ini ファイルを指定します。
3. Step.2 で、Display List ボタンをクリックします。次項以降の登録を以前に行っていたら、リストにその内容が表示されます。
3. Add user ボタンをクリックします。"Add New User" ウインドウが開きます。
4. ログインするユーザーの id ファイルを指定して、OK ボタンをクリックします。ウインドウが閉じて、リストにユーザーの情報が追加されていることを確認します。
5. Save list ボタンをクリックします。
6. Close ボタンで閉じます。
7. SQLサーバコンピュータで、Windows￥SysWow64 (C:￥Windows￥SysWow64 など) フォルダ内にある32ビットドライバ用の ODBC データソース アドミニストレータ (odbcad32.exe) を開きます（もし32ビット版 Windows を使用しているのであれば、そもそも32ビットドライバ用だけが用意されているので、管理ツール内の「データソース(ODBC)」を使います。64ビット版 Windows の場合は、管理ツール内に用意されているものは 64ビットドライバ用なので、32ビットドライバ用を探ってつかいます）
8. 「システムDSN」タブで、追加ボタンをクリックします。
9. データソースのドライバーに Lotus Notes SQL Driver (*.nsf) を選択して、完了ボタンをクリックします。
![f2_.png](https://qiita-image-store.s3.amazonaws.com/0/100206/53b71558-008c-24b2-2623-bd0cdfd452ae.png)
10. ODBC Lotesu Notes Setup ウインドウで、Data soure name 欄には任意の ODBC データソース名を入力します。
11. Domino server欄のコンボボックスを展開してみます。ノーツユーザーのパスワード入力ウインドウが表示されるので、"Notes SQL Authentication List Manager"で登録したノーツユーザーのパスワードを入力します。すると、サーバ一がリストアップされますので、接続したいサーバを選択します。
12. Database 欄には、既定で接続したいノーツのデータベースを指定します。
13. OK ボタンをクリックして閉じます。

###クライアントですること
1. SQL Server Management Studio を開き、MSSQLServer へ管理者権限（リンクサーバ登録などができるユーザー）でログインします。
2. オブジェクト エクスプローラー内から「リンク サーバ」項目をさがし出します。右クリックをして「新しいリンク サーバ」を選択します。
3. 「全般」ページで、リンクサーバー欄に任意のリンクサーバーの名前を入力します。種類には「その他のデータソース」を選択し、プロバイダーには Microsoft OLE DB Provider for ODBC Drivers を選択し、プロバイダー文字列に DSN=データソース名 を入力します。他は空欄で大丈夫です。
4. 「セキュリティ」ページで、「このセキュリティ コンテキストを使用する」を選択、リモートログイン欄には、ノーツユーザー名（ドメイン名まできちんと入力）、パスワード欄にはノーツユーザーのログインパスワードを入力します。
5. OK ボタンをクリックします。エラーが出ずに登録されればリンクサーバの登録が終わりました。
6. 登録されたリンクサーバの項目から、テーブルやビューを展開してみます。一覧が表示されたら、無事接続できたと考えて大丈夫です。

###クエリーしてみる
1. クライアントで SQL Server Management Studio を開き、MSSQLServer へログインします。
2. SQLペインで、次のような SQL 文を記述して発行してみます。

```sql
 -- リンクサーバ名に引用符は不要
 -- ノーツのビュー名は [] などで囲ったりしないでそのまま記述する
 SELECT * FROM OPENQUERY(リンクサーバ名, 'SELECT * FROM ノーツのビュー名');
```

検索結果は表示されたでしょうか？

##Tips
[公式ドキュメント](https://www.ibm.com/developerworks/lotus/documentation/notessql/)があります（英語）。
（下記内容はドキュメント参照前に記載したものもあります）
###データ取得方法についてのTips
<dl>
<dt>どんな DDL が使える？</dt><dd>ALTER TABLE, CREATE INDEX, CREATE TABLE, CREATE VIEW, DROP INDEX, DROP TABLE, DROP VIEW が使えます（公式ドキュメント <a href="http://www-12.lotus.com/ldd/doc/notessql/3.0.1/notes_sql.nsf/66208c256b4136a2852563c000646f8c/a7fe936e6f51f7c785256a71005647a3?OpenDocument" target=_blank>Summary of supported ODBC SQL grammar</a> より）</dd>
<dt>SELECT 文の文法は？</dt><dd>SELECT [DISTINCT] {*|列リスト} FROM ... WHERE ... GROUP BY ... HAVING ... UNION ... のようです（公式ドキュメントより）</dd>
<dt>列のデータ型の種類は？</dt><dd>フォームに関しては、公式ドキュメントの "Data types" に対応表があります。ビューに関しては、すべてVARCHAR(SQL_VARCHAR)で返されます（公式ドキュメント "Using SQL tables derived from Notes forms and views" より）</dd>
<dt>どんな比較演算子を使える？</dt><dd>＜, ＞, ＜＝, ＞＝, ＝, ＜＞, BETWEEN, IN, LIKE, NOT, ANY, SOME（ANY と同じ）, ALL, EXISTS が使えます（公式ドキュメント "Predicate operators" より）</dd>
<dt>どんな関数を使える？</dt><dd>AVG, COUNT, MAX, MIN, SUM が使えます（公式ドキュメント <a href="http://www-12.lotus.com/ldd/doc/notessql/3.0.1/notes_sql.nsf/66208c256b4136a2852563c000646f8c/033fd8a17dc1c55785256a7100564a8e?OpenDocument" target=_blank>Column functions</a> より）</dd>
<dt>NoteID や更新日時などを得たい（疑似列）</dt><dd>公式ドキュメントの <a href="http://www-12.lotus.com/ldd/doc/notessql/3.0.1/notes_sql.nsf/66208c256b4136a2852563c000646f8c/91b4e2a92535b4c585256a7100563ab8" target=_blank>Using Notes internal fields</a> によると、NotesID, NoteRef, NoteCreated, NoteModified, NoteAccessed, NoteFile, NoteForm, NoteFormType, NoteUNID, NoteRefUNID, NoteConflict の内部列名を利用できるようです。</dd>
<dt>NotesUrlを得たい</dt><dd>こちらの方の情報「<a href="http://guylocke.blogspot.jp/2008/10/notesurl.html">NotesURLを作成する方法（@関数の場合） のおつ -Notes/Dominoに関すること-</a>」が有用です。感謝！！</dd>
<dt>ビューの列名が、見出し（ヘッダ）と違って _＄1 とか _＄25 とかなっている</dt><dd>暗黙で割り振られるようですが、デザイナから変更できます。ビュー列のプロパティのプログラムの使用セクションに「名前」項目があるので、ここに指定すれば変更できます（公式ドキュメント "Using SQL tables derived from Notes forms and views" より）</dd>
<dt>OPENQUERYでのSELECT...WHERE句がなんか変</dt>
<dd>SELECT * FROM TBL WHERE '2012-01-01' ＜ COL ならうまくヒットするのに、SELECT * FROM TBL WHERE COL ＞ '2012-01-01' だとヒットしない場合があります（不等号の向きが小なりのみ使えるのかな？）でも、大丈夫なときは大なり記号を使ってもうまくいきます。詳細調査中...</dd>
<dt>SQLの実行プランを取得できる？</dt><dd>「ODBC データソース アドミニストレータ」を開くと、「トレース」と書かれたタブがあり、これを利用できます（公式ドキュメント "The Notes SQL trace utility" より）</dd>
</dl>
###エラーについてのTips
####ログイン時
<dl>
<dt>Unable to validate userid ****</dt><dd>該当ユーザーについて、Authentication List Manager で、ID登録が完了していない可能性があります。[Add User]で登録したあと、[Save List]ボタンをクリックして登録が完了します。</dd>
</dl>
####SQLに関するエラー
<dl>
<dt>Invalid character</dt><dd>テーブル名、ビュー名、列名などを ""（二重引用符）で囲ってみると、解消されるかもしれません（オブジェクト名の先頭が数字のときに発生しました）</dd>
<dt>Incompatible data types in comparison</dt><dd>WHERE句で、数字リテラルを使った比較をしようとした場合に発生することがあります。数字のつもりのフィールドでも、文字列扱いになっている場合（とくにビューの場合は、すべて文字列型で返されます）があります。自動で変換してくれませんので、自前で数値を文字列に変換しておきます。</dd>
<dt>リンク サーバー "******" の OLE DB プロバイダー "MSDASQL" のスキーマまたはカタログの使用は無効です。4 部構成の名前が指定されましたが、このプロバイダーではカタログまたはスキーマを使用するのに必要なインターフェイスが公開されていません。</dt><dd>一般的なSELECT文（リンクサーバオブジェクト指定）ではクエリーできず、T-SQLの<a href="https://docs.microsoft.com/ja-jp/sql/t-sql/functions/openquery-transact-sql" target=_blank>OPENQUERY</a>関数を使用してアクセスする必要があるようです。すなわち<br>
SELECT * FROM [DOMINOLINK].[default].dbo.TargetView<br>ではなく<br>
SELECT * FROM OPENQUERY([DOMINOLINK], 'SELECT * FROM TargetView')<br>と指定します。<br>テーブル名やビュー名は、SQL Server Management Studio で、リンクサーバー内のカタログを展開したときに表示されるオブジェクト表現に倣います（括弧がアンダースコアに変換されたりしています。(MyView) が _MyView_ であったり）</dd>

</dl>

---
間違いのご指摘や補足情報、お待ちしています！

#参考情報
感謝申し上げます！
- [IBM Lotus NotesSQL (IBM Developer Works)](http://www.ibm.com/developerworks/lotus/products/notesdomino/notessql/)
- [Connect to Lotus Domino using SQL Server Linked Server](http://www.databasejournal.com/features/mssql/article.php/3462011/Connect-to-Lotus-Domino-using-SQL-Server-Linked-Server.htm)
- [IBM 技術情報 NotesSQL を利用するためのガイド](http://www-01.ibm.com/support/docview.wss?uid=swg21693694)
- [QA@IT SQLserverからNotesのDBを参照したい](http://qa.atmarkit.co.jp/q/5239)
- [ワルブリックス株式会社 64bit Windowsで 32bitのODBCドライバを使う](http://www.walbrix.com/jp/blog/2007-12-64bit-windows-32bitodbc.html)
- [株式会社ITサポートさくら ODBC/64bit版Windowsで32bit版ODBCの設定を行う方法](http://db.just4fun.biz/ODBC/64bit%E7%89%88Windows%E3%81%A732bit%E7%89%88ODBC%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E8%A1%8C%E3%81%86%E6%96%B9%E6%B3%95.html)
- [Using the new IBM ODBC Driver for Notes/Domino 9.0](https://www.slideshare.net/MatNewman/using-the-new-ibm-odbc-driver-for-notesdomino-90) - Mat Newmanさん
- [User name and password errors](http://www-12.lotus.com/ldd/doc/notessql/3.0.2c/notessql.nsf/4d74586c8dcad500852563c000646f90/1cd32db55d64f94185256cf4006eb2f8?OpenDocument) - lotus.com
- [Application integration: Create an ODBC connection to a Lotus Notes database](https://www.techrepublic.com/article/application-integration-create-an-odbc-connection-to-a-lotus-notes-database/) - Greg Griffithsさん