- PR -

VBAでsqlserverの主キーを取得したい。でもエラーが

1
投稿者投稿内容
take
大ベテラン
会議室デビュー日: 2004/08/13
投稿数: 177
お住まい・勤務地: 沖縄県北部
投稿日時: 2006-04-13 10:46
いつもお世話になります。SQLSERVER2000、EXCEL2000VBAです。
DBの定義をVBAで取得しようと思ってます。テーブル名、フィールド名、
NOTNULL制約等は取得できたのですが、主キーを取得しようと下のコード
を実行すると、
「オブジェクトまたはプロバイダは要求された操作を実行できません」
というエラーメッセージが出ます。

コード:
    Dim cn As ADODB.Connection
    Dim cat As ADOX.Catalog
    Dim tbl As ADOX.Table
    Dim col As ADOX.Column
    Dim idx As ADOX.Index
    Dim Rs As ADODB.Recordset
    Set cn = New ADODB.Connection
    Set cat = New ADOX.Catalog
    Set Rs = New ADODB.Recordset
    Dim strRet As String
    
    cn.Open DSNName
    cat.ActiveConnection = cn
    フィールドカウント = 0
    For i = 0 To Rs.Fields.Count - 1
        If cat.Tables(テーブル名).Keys(0).Columns(i).Name _
         = Rs.Fields(i).Name Then
            DB.キー(フィールドカウント) = "○"
        End If
    Next 'i-next



主キーの判定のところのロジックが多少おかしいのは分かりますが、
そもそもエラーメッセージからするとsqlserverでは対応してない
取り方なのかとも思っております。
cat.Tables(テーブル名).Keys(0)で情報を取ろうとするとエラーに
なるようです。

他の対応方法、もしくは修正方法をご存知の方がいらっしゃいましたら
ご教授のほどよろしくお願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-04-13 11:07
引用:

takeさんの書き込み (2006-04-13 10:46) より:

主キーの判定のところのロジックが多少おかしいのは分かりますが、


というよりは、なぜ Recordset が必要なのでしょうか?

コード:

    Private Sub MakiMakiLove()
        Dim hConnection As ADODB.Connection
        Set hConnection = New ADODB.Connection

        hConnection.ConnectionString = "Provider=SQLOLEDB; Data Source=Server; Initial Catalog=NorthWind; Integrated Security=SSPI;"
        On Error GoTo CatchOpenException
        Call hConnection.Open
        On Error GoTo FinallyDispose

        Dim hCatalog As ADOX.Catalog
        Set hCatalog = New ADOX.Catalog
        hCatalog.ActiveConnection = hConnection

        Dim i As Integer
        For i = 0 To hCatalog.Tables("Orders").Keys.Count - 1
            Call MsgBox(hCatalog.Tables("Orders").Keys(i).Name)
        Next i

    FinallyDispose:
        If Not hConnection Is Nothing Then
            If hConnection.State <> adStateClosed Then
                Call hConnection.Close
            End If
        End If
        Exit Sub

    CatchOpenException:
        Call MsgBox("データベース接続が確立できませんですた")
    End Sub


こんな感じで良いのではないでしょうか? (試していませんが)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
take
大ベテラン
会議室デビュー日: 2004/08/13
投稿数: 177
お住まい・勤務地: 沖縄県北部
投稿日時: 2006-04-13 11:48
じゃんぬさん、ご返答ありがとうございます。
引用:

じゃんぬねっとさんの書き込み (2006-04-13 11:07) より:
なぜ Recordset が必要なのでしょうか?



すみません、消し忘れです。後続の処理で使用するもので・・・(汗)
プロバイダを変更してSQLOLEDBにするとkeysプロパティが使える
ようになったみたいです。
ただ、主キーがどのフィールドに対応してるのかを取得したい時に
どのようにしたらいいのかが分かりません。主キーの数を数えようと
して下のようにしてみると前回と同じくプロバイダエラーになってしまい
ます。

Debug.Print cat.Tables("T_New").Keys(0).Columns.Count

というよりもまず、ADOXについて根本的に分かってないので調べ方等も
教えていただけると回答していただく方の時間を無駄にしなくていいような
気もします。
皆様はどのようにして調べていらっしゃるのでしょうか?

また、主キーに対応するフィールドの取得はどのようにしたらいいのでしょう?
すみませんが、引き続きよろしくお願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-04-13 13:13
引用:

takeさんの書き込み (2006-04-13 11:48) より:

また、主キーに対応するフィールドの取得はどのようにしたらいいのでしょう?
すみませんが、引き続きよろしくお願いします。


失礼しました、フィールド名の取得だったのですね。
多分こうだと思います。(先ほど同様、試していません)

コード:

    Private Sub MosaMosaAA()
        Dim hConnection As ADODB.Connection
        Set hConnection = New ADODB.Connection

        hConnection.ConnectionString = _
            "Provider=SQLOLEDB;" & _
            "Data Source=Server;" & _
            "Initial Catalog=NorthWind;" & _
            "Integrated Security=SSPI;"

        On Error GoTo CatchOpenException
        Call hConnection.Open
        On Error GoTo FinallyDispose

        Dim hCatalog As ADOX.Catalog
        Set hCatalog = New ADOX.Catalog
        Set hCatalog.ActiveConnection = hConnection

        Dim hTable As ADOX.Table
        Set hTable = hCatalog.Tables("Orders")

        Dim i As Integer
        For i = 0 To hTable.Indexes.Count - 1
            Dim hIndex As ADOX.Index
            Set hIndex = hTable.Indexes(i)

            If hIndex.PrimaryKey Then
                Dim j As Integer
                For j = 0 To hIndex.Columns.Count - 1
                    Call MsgBox(hIndex.Columns(j).Name)
                Next j
            End If
        Next i

    FinallyDispose:
        If Not hConnection Is Nothing Then
            If hConnection.State <> adStateClosed Then
                Call hConnection.Close
            End If
        End If
        Exit Sub

    CatchOpenException:
        Call MsgBox("データベース接続が確立できませんですた")
    End Sub


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
take
大ベテラン
会議室デビュー日: 2004/08/13
投稿数: 177
お住まい・勤務地: 沖縄県北部
投稿日時: 2006-04-13 15:08
じゃんぬさん、ありがとうございます。
やりたい処理ができました。下のように関数化して使わせてもらってます。
自分的にかなり便利です。

コード:
Function IsP_key(cat As ADOX.Catalog, TblName As String, FldName As String) As Boolean
   
        Dim hTable As ADOX.Table
        Set hTable = cat.Tables(TblName)

        Dim i As Integer
        For i = 0 To hTable.Indexes.Count - 1
            Dim hIndex As ADOX.Index
            Set hIndex = hTable.Indexes(i)

            If hIndex.PrimaryKey Then
                Dim j As Integer
                For j = 0 To hIndex.Columns.Count - 1
                    If hIndex.Columns(j).Name = FldName Then
                        IsP_key = True
                    Else
                        IsP_key = False
                    End If
                    Exit Function
                Next j
            End If
        Next i

End Function



あと、じゃんぬさんはベテランで経験も豊富なのでこんなこと質問
すること自体失礼だと思うのですが、どのようにして上のような
処理を実現するコードを調べたりするんでしょうか?
自分は恥ずかしながら自分で調べるも最後は掲示板で聞かないと解決
しないということが多々あるもので・・・。

take
大ベテラン
会議室デビュー日: 2004/08/13
投稿数: 177
お住まい・勤務地: 沖縄県北部
投稿日時: 2006-04-13 16:02
すみません、自分でコードをアップしておきながら不具合が
ありましたので修正しました。

コード:
Function IsP_key(cat As ADOX.Catalog, TblName As String, FldName As String) As Boolean
   
        Dim hTable As ADOX.Table
        Set hTable = cat.Tables(TblName)
        
        IsP_key = False
        
        Dim i As Integer
        For i = 0 To hTable.Indexes.Count - 1
            Dim hIndex As ADOX.Index
            Set hIndex = hTable.Indexes(i)

            If hIndex.PrimaryKey Then
                Dim j As Integer
                For j = 0 To hIndex.Columns.Count - 1
                    If hIndex.Columns(j).Name = FldName Then
                        IsP_key = True
                    End If
                Next j
            End If
        Next i

End Function


じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-04-13 16:07
引用:

takeさんの書き込み (2006-04-13 15:08) より:

あと、じゃんぬさんはベテランで経験も豊富なのでこんなこと質問
すること自体失礼だと思うのですが、


実際に実行して確認ができれば良いのですが、今回のように試せないものは、
「試していません」と明記して、ちょっと逃げ道を作っていますw

そうでなくても、間違っていて他の回答者さんからフォロー受けることもあります。
ですので「ベテラン」だなんてとんでもないです。(;^-^)

引用:

どのようにして上のような処理を実現するコードを調べたりするんでしょうか?


ほとんどリファレンスですね。
Microsoft 系、Sun Microsystems 系のものはネット上にゴロゴロしてますから。
(それ以外の場合も言語仕様書とか、まあリファレンス命ですね)

欲しい機能がどこにあるのかを知るには、ある程度数をこなす必要があると思います。

数をこなすと、ある程度のコモンセンスが磨きあがってきて、
「このクラス (オブジェクト) にはこのメンバがあるはずだ」という考え方ができるようになります。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
take
大ベテラン
会議室デビュー日: 2004/08/13
投稿数: 177
お住まい・勤務地: 沖縄県北部
投稿日時: 2006-04-13 16:21
引用:

じゃんぬねっとさんの書き込み (2006-04-13 16:07) より:
数をこなすと、ある程度のコモンセンスが磨きあがってきて、
「このクラス (オブジェクト) にはこのメンバがあるはずだ」という考え方ができるようになります。




なるほど。リファレンス&場数が命ということですね!
うーん・・・。ちょっと今の段階ではどこにリファレンスがあるのかも
わからない状態なのですが、VBの場合はMSDNを参照するとか
JAVAならSUNのクラスライブラリを参照するという認識で
いいのかなと理解してます。やっぱりそれ見てもある程度場数
こなしてないとなんのこっちゃさっぱり分からないですね。

助かりました。ありがとうございます。
1

スキルアップ/キャリアアップ(JOB@IT)