初めて投稿します。JMENOと申します。よろしくお願いします。
環境 WindowsXP Pro SP2 +VB6 SP6 (ただし、VS2005 SP1をインストール済みの環境)なお、msjet40.dllのバージョンは4.00.8618.0です。
AccessはVer2002 SP3です。
VBで作成したFunctionをSQLに埋め込む際のエラーへの超基本的な質問です。
ユーザー定義関数として値を返すFunc1を作成します。
(コード)
■標準モジュール
Public cnn As ADODB.Connection
Public Function Func1(intI As Integer) As Integer
If intI = 1 Then
Func1 = intI * 10
Else
Func1 = intI * 100
End If
End Function
■Form1
Private Sub Form_Load()
Dim strCnn As String
Set cnn = New ADODB.Connection
strCnn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
& App.Path & "\dbTest.mdb"
cnn.ConnectionString = strCnn
cnn.Open
End Sub
Private Sub Command1_Click()
Call UpdateData
End Sub
Private Sub UpdateData()
Dim strSQL As String
strSQL = "UPDATE tableA Set Col2=Func1(Col1)"
'→ここで実行時エラー -2147217900(80040e14)
'式に未定義関数 'Func1' があります。
cnn.Execute (strSQL)
End Sub
この状態で実行すると「式に未定義関数 'Func1' があります」の実行時エラーが発生します。
最近、Jetを使う機会がなく、以前はJetでも関数埋め込みはできたはずだと思い、ネットを探しますが、答えがわからず投稿させていただきました。
なお、Registry HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\engines\SandboxModeの値は0に設定しています。
http://support.microsoft.com/?scid=kb%3Bja%3B239482&x=17&y=14
当然ですが、Accessの中に上記の処理を書くと問題なく実行できます。
VBのファンクションを含んでのSQL操作は無理だったでしょうか?
(SELECT文内に埋め込んでも結果は一緒です。)
>■標準モジュール
って VB の標準モジュールのこと?
いや、だって。。。SQL文を実行するのはデータベース(Access)でしょ?
でも Func1 があるのは VB の実行ファイルの中でしょ?
…全く別の場所じゃん???
…物理的に何の関係も無い場所の情報を、どうやって Access が知ることが
できると思えるのか不思議でなりません。
結局どこで実行したいのでしょう?VB 側で計算したいなら、計算結果だけ
Access に渡せばいいのでは?
特攻隊長まるるう 様
早速のご回答ありがとうございました。
普段PL/SQLばかり使っているので勘違いしていました。
○VBからOracleへのSQLの実行
ストアドされた関数はOracle側の関数なのでOracleエンジン側で実行。
VBからはストアドされたエンジン側のFUNCTIONを呼び出すため、SQL文内に書 いても実行可能。
○VBからJETエンジンへのSQL実行
=>JETエンジン側で認識できる関数であれば実行可能?
=>例えばFUNCTIONをmdb側に用意したうえで、VB側からAccessのインスタンス を作成し、関数呼び出しができれば可能?
というような理解でよろしいでしょうか?
○代替えとしてmdb側でアクションクエリを準備したうえで、Accessのインスタ ンスをVB側で作成し、DoCmd.OpenQueryで実行すればよいかなと考えていま す。
※ここ数日、上記のことで思い悩んでおりましたので、踏ん切りがつきました。
ありがとうございました。
あー。カラムの値によって更新する値を変更したいのね。
# そーいえば Access ってストアド無いんでしたっけ?(汗)
# 正直なところ知りません。
Access をデータベースと思っていないので、ボクはそのレベルの回答
しかできません。Access を対象としたサイトで質問したほうがいいですよ。
丸っきりデータベースの機能に依存する話ですから。
>○VBからOracleへのSQLの実行
> ストアドされた関数はOracle側の関数なのでOracleエンジン側で実行。
> VBからはストアドされたエンジン側のFUNCTIONを呼び出すため、SQL文内に書 いても実行可能。
『ストアドされた関数』って時点で前提条件が崩れてますが?(^^;
VB から呼び出すのは最初のストアドのみで、そのストアドは Oracle で実行されますよね?
そこで使っている関数を『VBは関知しない』でしょう?
Access でも同じです。
>○VBからJETエンジンへのSQL実行
> =>JETエンジン側で認識できる関数であれば実行可能?
単純に集計関数は実行可能ですよね?
# Swith 関数、IIF 関数などが使えませんでしたっけ?
> =>例えばFUNCTIONをmdb側に用意したうえで、VB側からAccessのインスタンス を作成し、関数呼び出しができれば可能?
Access のインスタンスを生成して参照できるのは、Access に実装されているものだけでは?
自作の関数が公開できると Access そのものを改造したことになっちゃうのでは?
それって違法では?w
# Excel では Run メソッドへ関数名と引数を渡すことで実現できますが、自作の関数を公開
# できているわけではありません。Access にそのようなものが用意されているかどうかは
# 知りません。
というか、Oracleと同じ条件で理解するなら、完全に Access 側の話ですよね。
… VB は関知しません。
特攻隊長まるるう 様
ご回答ありがとうございました。
>># そーいえば Access ってストアド無いんでしたっけ?(汗)
>># 正直なところ知りません。
>>Access をデータベースと思っていないので、ボクはそのレベルの回答
そうですね。ストアドもありませんし、SQLを投げても中で何やってるか
全くわかりません。
>>自作の関数が公開できると Access そのものを改造したことになっちゃうのでは?
>>それって違法では?w
これについては正直調べてみないとわかりませんが、実際上の問題として、
インスタンスを作成してもSQL内でそのインスタンス内のオブジェクトの指定が
難しいようです。(例えば、レポートを指定して実行するなどはSQL文字列と
関係ないのでobjAccess.DoCmd.OpenReportで簡単に指定できますが、
SQL文内ではインスタンスの名称を渡しても当然ながら認識できません。)
今回はSQLによる直接の指定はあきらめ、mdb側に関数とクエリを用意し、
それを呼び出す形で対処したいと思います。
ありがとうございました。
特攻隊長まるるう 様
ありがとうございました。
一応、解決ということで処理させていただきます。