「Access」の編集履歴(バックアップ)一覧はこちら
「Access」(2012/07/30 (月) 12:26:32) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
PageLastUpdate:&date()/today:&counter(today)/yesterday:&counter(yesterday)
#contents()
このページの記述はMicrosoft Access 2002に基づいています。
*&aname(アクセスアドインをユーザー権限で使用する){アクセスアドインをユーザー権限で使用する}
2009/11/04 環境:Windows XP,Access XP(2002)
ユーザー権限でアドインをインストールしようとすると下記エラーメッセージが出る。
>レジストリへの追加中にエラーが発生しました。
レジストリ[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\10.0\Access]に使わせたいユーザーが書き込めるような権限を設定すればよい
変更点を追いかけるだけだと[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\10.0\Access\Menu Add-Ins]に権限を与えればよさそうに見えますが、Accessキーも書き込み可能でOpenしていると思われます。
もちろんセキュリティリスクがありますので自己責任で。
*&aname(Accessの最大の問題点とは){Accessの最大の問題点とは}
2009/07/01
Accessは信じられないほどよくできたツールだと思ってます。私のデータベース技術もプログラミング技術も、これがなければ職業にできるレベルにならなかった、たぶん。
.netもクリスタルレポートいらないから、Accessのレポート機能そのまま移植してくれ、という感じで。
そんなAccessの最大の問題点は何かという話。
いつのまにかネットワーク管理者、データベース管理者になってしまった私から見た場合、
「Accessで作ったアプリケーションはユーザーに変更権限があり、悪意のあるプログラムが組み込まれる可能性を否定できない」
というところ。
自分自身がユーザーである間は関係ないんですけどね。
仕込みをしておいて管理者権限で動作されるのをじっと待つようなこともできるし。
もちろん書き換えられないように作ることも大分苦労すればできますけど、割には合わないかな。
だからAccessはツールとして使って、アプリケーションとして使わない。人には渡さない。
人から渡されたAccessを管理者権限で開くことはしない、とか、そんな今日この頃。
*&aname(アプリケーションDB/データDB/ワークDBをセットで使う){アプリケーションDB/データDB/ワークDBをセットで使う}
下記の情報は2001年ごろに書いたもので、Access2003までには当てはまりますが、Access2007でどうなのかは不明です。
古い文書なので今見るとおかしなところもありますねが、めんどくさいのでそのまま公開。
#blockquote(){**ネットワークでのAccessデータベースの使用とパフォーマンスの向上
***分散型データベース
Accessデータベースはデータ部分(テーブル)とアプリケーション部分(クエリー/フォーム/レポート/マクロ/モジュール)が同じファイルに保存されています。これは、データを更新するたびにファイルを保存する動作を繰り返しているということで、同じファイル上にあるアプリケーション部分も常に書き換えの危険性にさらされていることになります。Accessデータベースはサイズが大きくなるに従って、ファイルの壊れる確立が飛躍的に上がってしまいます。
一定以上の安定性を必要とするデータベースを構築するときは、SQLサーバーなどにテーブルを持つのが望ましいのですが、そうすると開発・運用が個人レベルでは行えなくなります。そのため、Accessで数万件の頻繁に変更を繰り返すデータベースを組む際に、アプリケーション部分とデータ部分を分割して、テーブルはすべてリンクによって処理します。これをアプリケーションDB、データDBと呼ぶことにします。
また、Accessはいったん追加したレコードを削除しても、最適化を行うまではデータベースサイズが小さくならないという欠点も持っています。このため、一時的にテーブルを作成する場合などは、アプリケーションDBやデータDBでは作業を行わず、作業用のデータベースを作っておきます。これをテンポラリDBと呼ぶことにします。
アプリケーションDB、データDB、デンポラリDBの3つを使ってデータベースを構築することで、数十万件程度であれば安定して稼動するデータベースを構築することができます。これが分散型データベースのテクニックです。
ローカルディスクの特性を生かした高速化
基本的な知識として、サーバーへの書き込みはローカルへの書き込みよりかなり遅くなります(読み取りもほぼ同じです)。理由は「回線速度」と「サーバーの応答」です。
「回線速度」のイメージは、ローカルへの書き込みというのは「バケツを逆さにして他のバケツに水を移す」ことで、サーバーへの書き込みというのは「バケツからバケツにホースにで水を移す」ことです。
「サーバーの応答」のイメージとしては、ローカルへの書き込みというのは「自分で文章を書く」ことで、サーバーへの書き込みというのは、「自分が読み上げる文章を電話先の相手にメモさせる」ことだと思ってください。相手がなんと言ったのか、聞き返しながら書くことになります。おまけにサーバーにはいろいろな人からひっきりなしに電話がかかってきます。当然、話中のこともあります(たとえ話ですよ)。
ですから、Accessを使う大前提は、「ローカルで使ったほうが速い」ということです。
また、数人で共用するデータベースはサーバー上において使いますが、Accessはユーザーが認識していなくてもアプリケーション部分も書き換えています。たとえばレポートの印刷設定を変更したり、データシートの列の順番を変更した結果はアプリケーションDBに書き込まれます。このため、複数人でアプリケーションDBを共有すると、破損確立が極端に上がります。
ここから、分散型データベースの最適な形は、
-全員で共有するべきデータと設定はサーバー上のデータDBにテーブルとして持つ。
-個人的な設定を保存するテーブルはアプリケーションDBに持ち、アプリケーションDBはローカルに置く。
-テンポラリDBはローカルに置く。
ことだというのがわかると思います。
ただし、デメリットとしてアプリケーションのバージョンアップが行いにくいということがあげられます。ローカルのアプリケーションDBをバージョンアップしなくてはならないので、なんらかの形で自動バージョンアップの機能を用意するのが望ましいでしょう。
***テンポラリDBの複写テクニック
一時的に使用したデータをクリアするのに削除クエリーを使うのは、あまり得策ではありません。数百件であればそう時間もかかりませんが、処理を繰り返すことによってテンポラリDBが大きくなっていきます。テンポラリDBの破損は処理の中断に繋がりますから、なんとか避けなければいけません。
ここで発想の転換をします。どうせすべてのテーブルをクリアしてよいのであれば、最初からすべてのテーブルにデータのないきれいなファイルを上書きしてやれば、クリアするより早く、確実です。テーブルのリンクは上書きしたテンポラリDBに対してきちんと有効になります。
具体的にはTEMP.MDBとTEMP.NEWのように同じテンポラリDBを名前を変えてふたつ用意して、通常の処理にはTEMP.MDBを使います。テンポラリの中身をすべて破棄してよいタイミングで、TEMP.NEWをTEMP.MDBに上書きしてやります。
**分散型データベース構築のためのオリジナル関数の例
LINKfromDB(データベースPath)
指定したデータベースのテーブルをすべてリンクします。このとき、同じリンクテーブル名がある場合はいったん削除してからリンクを張り直します。また、リンクテーブルではない同じテーブル名がある場合は、そのテーブルはリンクをしません。
DB_Copy(コピー元ファイル,コピー先ファイル)
テンポラリDBの複写を実現するための関数です。アプリケーションDBと同じフォルダにテンポラリDBを置けば、パス指定なしでコピーできます。また、コピーに失敗した場合には数回リトライし、最終的に失敗であれば、関数としてFalseを返します。
**更新行数を分割してパフォーマンスを向上させる
扱うデータが多量になるにつれ、データを書き換えるのが遅くなります。実際には遅くなるというよりは、処理が中断してしまい、データベースがフリーズするということになります。
Accessはクエリーでデータの書き換え/追加/削除をするときに、いったんメモリ上にそのクエリーの結果をすべて作ります。なぜなら、データの入力規則があっているか、キーの重複はないか、といったことは現状と結果の比較をしないとわからないからです。検証が終わってからはじめて、データベースに結果を書き込みます。
ざっくりと言えば、10MBのデータを書き換えるには20MB、20MBのデータを書き換えるには40MBのメモリを消費するということです。そのため多量のデータを一度で書き換えようとするとメモリが不足し、よくて失敗、悪ければフリーズするということになります。
結果の作成に成功したとしても、多量のデータを一気に書き込みにいきますので、書き込み中にエラーがおきる可能性も高くなります。
実際には追加や削除は数万件のデータでも扱えます。
フリーズするのは更新処理なので、私は数万行の処理を指定行数に分割して書き込んでやるような関数を組んでいます。
}
*&aname(SQLServerへのリンクテーブルで「データの競合」エラー){SQLServerへのリンクテーブルで「データの競合」エラー}
実際にはデータが競合していないのにSQLServerへの更新で「データの競合」エラーが出るパターン
-256文字以上のテキスト型のフィールドをリンクしていて、メモ型になっている。
-bitフィールドでNULLが存在する。
公式情報があるわけではないので、実体験からの推測です。検索してもほとんどひっかからなかったけど、SQLServerに直接リンクテーブルで更新かけるような使い方が少ないからだろうか?
2007/05/30 部分的ですがKBもあるようです。YU-TANGさんより。
http://support.microsoft.com/kb/280730
*&aname(Access複数のフォームの連動){Access複数のフォームの連動}
http://fukkey.dyndns.org/pins/acc/040930/90175.html
Set FormA.RecordSet=FormB.RecordSet
**メインフォームとサブフォームの関係でやるとうまくいかないことがある。
2007/04/24
ODBCリンクテーブルだからかも。会社でエラーが出たのでメッセージ載せられず・・・
>× Set Me.SubForm.Form.RecordSet=Me.RecordSet
メインのOpen/Load、サブのOpen/Loadでサブ→メイン/メイン→サブの8パターンやったがダメだった。
データに結合しない親フォームに複数のサブフォームとして置くと回避できた
>○ Set Me.SubFormA.Form.RecordSet=Me.SubFormB.Form.RecordSet
タイミングは親Formのロードで。
**並べ替えると連動が外れる
2007/04/26
Access2002の環境で発生。Access97だときちんとできていた気もするが未検証。
あ、ODBCだからかも。MDBのテーブルでは大丈夫かも。未検証。
「並べ替え後」というイベントはAccess2002では取れないので、両方のサブフォームのCurrentで、主キーを比較して異なっていたら再設定というめんどくさいことをやらざるを得なくなった。これだとイマイチ。
*&aname(親フォームと子フォームで発生するイベントの順番){親フォームと子フォームで発生するイベントの順番}
2007/05/25
+子のOPEN
+子のLOAD
+親のOPEN
+親のLOAD
*&aname(ユーザーから受けたQ&A){ユーザーから受けたQ&A}
**不一致クエリウィザードに使いたいフィールドが表示されない 2007/04/23
比較したいフィールドのデータ型が異なっているから。テーブルのデータ型を変更することで回避できる。
もちろんウィザードを使わずにSQLで書けば回避できるけど、それはここのネタではないか。
*&aname(よく使うサイト){よく使うサイト}
pin's Laboratory http://www7.big.or.jp/~pinball/discus/access/index.html
*&aname(アドインとか){アドインとか}
**おたすけあくせす
2007/05/12
とても便利。でもおかしい。ネット上のどこにもない。どこにいっちゃったの?なにがあったの?
**P/QueryEditor
2007/05/12 http://www.vector.co.jp/soft/winnt/business/se357128.html
クエリのSQLをデータシートで編集/管理
----
*comment
このページの記述で聞きたいこととか間違ってることとかありましたらコメントを。
#comment_num2
----
PageLastUpdate:&date()/today:&counter(today)/yesterday:&counter(yesterday)
#contents()
このページの記述はMicrosoft Access 2002に基づいています。
*&aname(OpenCurrentdbで指定するパスにスラッシュが含まれると、Accessデータベースが読み取り専用になる){OpenCurrentdbで指定するパスにスラッシュが含まれると、Accessデータベースが読み取り専用になる}
2012/07/30 環境:Windows 7,Office 2010
#blockquote(){このデータベースは読み取り専用で開いています。変更できるのは、リンク テーブル内のデータのみです。デザインを変更するには、データベースのコピーを保存して下さい。}
とメッセージバーが表示されてしまう。
物凄い悩んだ末に、パスの区切り文字をバックスラッシュ(円マーク)ではなくスラッシュで記載していたことが判明。
スラッシュで記述すると、URLとして認識されて、ネット上から起動した扱いになるのね。
XP+Office2002の環境では発生しない。
参考URL https://bugs.ruby-lang.org/issues/2947
*&aname(アクセスアドインをユーザー権限で使用する){アクセスアドインをユーザー権限で使用する}
2009/11/04 環境:Windows XP,Access XP(2002)
ユーザー権限でアドインをインストールしようとすると下記エラーメッセージが出る。
>レジストリへの追加中にエラーが発生しました。
レジストリ[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\10.0\Access]に使わせたいユーザーが書き込めるような権限を設定すればよい
変更点を追いかけるだけだと[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\10.0\Access\Menu Add-Ins]に権限を与えればよさそうに見えますが、Accessキーも書き込み可能でOpenしていると思われます。
もちろんセキュリティリスクがありますので自己責任で。
*&aname(Accessの最大の問題点とは){Accessの最大の問題点とは}
2009/07/01
Accessは信じられないほどよくできたツールだと思ってます。私のデータベース技術もプログラミング技術も、これがなければ職業にできるレベルにならなかった、たぶん。
.netもクリスタルレポートいらないから、Accessのレポート機能そのまま移植してくれ、という感じで。
そんなAccessの最大の問題点は何かという話。
いつのまにかネットワーク管理者、データベース管理者になってしまった私から見た場合、
「Accessで作ったアプリケーションはユーザーに変更権限があり、悪意のあるプログラムが組み込まれる可能性を否定できない」
というところ。
自分自身がユーザーである間は関係ないんですけどね。
仕込みをしておいて管理者権限で動作されるのをじっと待つようなこともできるし。
もちろん書き換えられないように作ることも大分苦労すればできますけど、割には合わないかな。
だからAccessはツールとして使って、アプリケーションとして使わない。人には渡さない。
人から渡されたAccessを管理者権限で開くことはしない、とか、そんな今日この頃。
*&aname(アプリケーションDB/データDB/ワークDBをセットで使う){アプリケーションDB/データDB/ワークDBをセットで使う}
下記の情報は2001年ごろに書いたもので、Access2003までには当てはまりますが、Access2007でどうなのかは不明です。
古い文書なので今見るとおかしなところもありますねが、めんどくさいのでそのまま公開。
#blockquote(){**ネットワークでのAccessデータベースの使用とパフォーマンスの向上
***分散型データベース
Accessデータベースはデータ部分(テーブル)とアプリケーション部分(クエリー/フォーム/レポート/マクロ/モジュール)が同じファイルに保存されています。これは、データを更新するたびにファイルを保存する動作を繰り返しているということで、同じファイル上にあるアプリケーション部分も常に書き換えの危険性にさらされていることになります。Accessデータベースはサイズが大きくなるに従って、ファイルの壊れる確立が飛躍的に上がってしまいます。
一定以上の安定性を必要とするデータベースを構築するときは、SQLサーバーなどにテーブルを持つのが望ましいのですが、そうすると開発・運用が個人レベルでは行えなくなります。そのため、Accessで数万件の頻繁に変更を繰り返すデータベースを組む際に、アプリケーション部分とデータ部分を分割して、テーブルはすべてリンクによって処理します。これをアプリケーションDB、データDBと呼ぶことにします。
また、Accessはいったん追加したレコードを削除しても、最適化を行うまではデータベースサイズが小さくならないという欠点も持っています。このため、一時的にテーブルを作成する場合などは、アプリケーションDBやデータDBでは作業を行わず、作業用のデータベースを作っておきます。これをテンポラリDBと呼ぶことにします。
アプリケーションDB、データDB、デンポラリDBの3つを使ってデータベースを構築することで、数十万件程度であれば安定して稼動するデータベースを構築することができます。これが分散型データベースのテクニックです。
ローカルディスクの特性を生かした高速化
基本的な知識として、サーバーへの書き込みはローカルへの書き込みよりかなり遅くなります(読み取りもほぼ同じです)。理由は「回線速度」と「サーバーの応答」です。
「回線速度」のイメージは、ローカルへの書き込みというのは「バケツを逆さにして他のバケツに水を移す」ことで、サーバーへの書き込みというのは「バケツからバケツにホースにで水を移す」ことです。
「サーバーの応答」のイメージとしては、ローカルへの書き込みというのは「自分で文章を書く」ことで、サーバーへの書き込みというのは、「自分が読み上げる文章を電話先の相手にメモさせる」ことだと思ってください。相手がなんと言ったのか、聞き返しながら書くことになります。おまけにサーバーにはいろいろな人からひっきりなしに電話がかかってきます。当然、話中のこともあります(たとえ話ですよ)。
ですから、Accessを使う大前提は、「ローカルで使ったほうが速い」ということです。
また、数人で共用するデータベースはサーバー上において使いますが、Accessはユーザーが認識していなくてもアプリケーション部分も書き換えています。たとえばレポートの印刷設定を変更したり、データシートの列の順番を変更した結果はアプリケーションDBに書き込まれます。このため、複数人でアプリケーションDBを共有すると、破損確立が極端に上がります。
ここから、分散型データベースの最適な形は、
-全員で共有するべきデータと設定はサーバー上のデータDBにテーブルとして持つ。
-個人的な設定を保存するテーブルはアプリケーションDBに持ち、アプリケーションDBはローカルに置く。
-テンポラリDBはローカルに置く。
ことだというのがわかると思います。
ただし、デメリットとしてアプリケーションのバージョンアップが行いにくいということがあげられます。ローカルのアプリケーションDBをバージョンアップしなくてはならないので、なんらかの形で自動バージョンアップの機能を用意するのが望ましいでしょう。
***テンポラリDBの複写テクニック
一時的に使用したデータをクリアするのに削除クエリーを使うのは、あまり得策ではありません。数百件であればそう時間もかかりませんが、処理を繰り返すことによってテンポラリDBが大きくなっていきます。テンポラリDBの破損は処理の中断に繋がりますから、なんとか避けなければいけません。
ここで発想の転換をします。どうせすべてのテーブルをクリアしてよいのであれば、最初からすべてのテーブルにデータのないきれいなファイルを上書きしてやれば、クリアするより早く、確実です。テーブルのリンクは上書きしたテンポラリDBに対してきちんと有効になります。
具体的にはTEMP.MDBとTEMP.NEWのように同じテンポラリDBを名前を変えてふたつ用意して、通常の処理にはTEMP.MDBを使います。テンポラリの中身をすべて破棄してよいタイミングで、TEMP.NEWをTEMP.MDBに上書きしてやります。
**分散型データベース構築のためのオリジナル関数の例
LINKfromDB(データベースPath)
指定したデータベースのテーブルをすべてリンクします。このとき、同じリンクテーブル名がある場合はいったん削除してからリンクを張り直します。また、リンクテーブルではない同じテーブル名がある場合は、そのテーブルはリンクをしません。
DB_Copy(コピー元ファイル,コピー先ファイル)
テンポラリDBの複写を実現するための関数です。アプリケーションDBと同じフォルダにテンポラリDBを置けば、パス指定なしでコピーできます。また、コピーに失敗した場合には数回リトライし、最終的に失敗であれば、関数としてFalseを返します。
**更新行数を分割してパフォーマンスを向上させる
扱うデータが多量になるにつれ、データを書き換えるのが遅くなります。実際には遅くなるというよりは、処理が中断してしまい、データベースがフリーズするということになります。
Accessはクエリーでデータの書き換え/追加/削除をするときに、いったんメモリ上にそのクエリーの結果をすべて作ります。なぜなら、データの入力規則があっているか、キーの重複はないか、といったことは現状と結果の比較をしないとわからないからです。検証が終わってからはじめて、データベースに結果を書き込みます。
ざっくりと言えば、10MBのデータを書き換えるには20MB、20MBのデータを書き換えるには40MBのメモリを消費するということです。そのため多量のデータを一度で書き換えようとするとメモリが不足し、よくて失敗、悪ければフリーズするということになります。
結果の作成に成功したとしても、多量のデータを一気に書き込みにいきますので、書き込み中にエラーがおきる可能性も高くなります。
実際には追加や削除は数万件のデータでも扱えます。
フリーズするのは更新処理なので、私は数万行の処理を指定行数に分割して書き込んでやるような関数を組んでいます。
}
*&aname(SQLServerへのリンクテーブルで「データの競合」エラー){SQLServerへのリンクテーブルで「データの競合」エラー}
実際にはデータが競合していないのにSQLServerへの更新で「データの競合」エラーが出るパターン
-256文字以上のテキスト型のフィールドをリンクしていて、メモ型になっている。
-bitフィールドでNULLが存在する。
公式情報があるわけではないので、実体験からの推測です。検索してもほとんどひっかからなかったけど、SQLServerに直接リンクテーブルで更新かけるような使い方が少ないからだろうか?
2007/05/30 部分的ですがKBもあるようです。YU-TANGさんより。
http://support.microsoft.com/kb/280730
*&aname(Access複数のフォームの連動){Access複数のフォームの連動}
http://fukkey.dyndns.org/pins/acc/040930/90175.html
Set FormA.RecordSet=FormB.RecordSet
**メインフォームとサブフォームの関係でやるとうまくいかないことがある。
2007/04/24
ODBCリンクテーブルだからかも。会社でエラーが出たのでメッセージ載せられず・・・
>× Set Me.SubForm.Form.RecordSet=Me.RecordSet
メインのOpen/Load、サブのOpen/Loadでサブ→メイン/メイン→サブの8パターンやったがダメだった。
データに結合しない親フォームに複数のサブフォームとして置くと回避できた
>○ Set Me.SubFormA.Form.RecordSet=Me.SubFormB.Form.RecordSet
タイミングは親Formのロードで。
**並べ替えると連動が外れる
2007/04/26
Access2002の環境で発生。Access97だときちんとできていた気もするが未検証。
あ、ODBCだからかも。MDBのテーブルでは大丈夫かも。未検証。
「並べ替え後」というイベントはAccess2002では取れないので、両方のサブフォームのCurrentで、主キーを比較して異なっていたら再設定というめんどくさいことをやらざるを得なくなった。これだとイマイチ。
*&aname(親フォームと子フォームで発生するイベントの順番){親フォームと子フォームで発生するイベントの順番}
2007/05/25
+子のOPEN
+子のLOAD
+親のOPEN
+親のLOAD
*&aname(ユーザーから受けたQ&A){ユーザーから受けたQ&A}
**不一致クエリウィザードに使いたいフィールドが表示されない 2007/04/23
比較したいフィールドのデータ型が異なっているから。テーブルのデータ型を変更することで回避できる。
もちろんウィザードを使わずにSQLで書けば回避できるけど、それはここのネタではないか。
*&aname(よく使うサイト){よく使うサイト}
pin's Laboratory http://www7.big.or.jp/~pinball/discus/access/index.html
*&aname(アドインとか){アドインとか}
**おたすけあくせす
2007/05/12
とても便利。でもおかしい。ネット上のどこにもない。どこにいっちゃったの?なにがあったの?
**P/QueryEditor
2007/05/12 http://www.vector.co.jp/soft/winnt/business/se357128.html
クエリのSQLをデータシートで編集/管理
----
*comment
このページの記述で聞きたいこととか間違ってることとかありましたらコメントを。
#comment_num2
----