none
データテーブルがクリアできない? RRS feed

  • 質問

  • VBもRDBMSも初心者です。

    VB2005でデータベースの表示をしようとしています。

    プログラムは以下です。
    Public Sub LoadDatabaseIND()
            Dim fs As String = ""
            Dim sql As String
            sql = "SELECT * FROM tbl_tag WHERE tag_type = 'IND' "
            Dim da As New System.Data.Odbc.OdbcDataAdapter(sql, My.Settings.iodbConnectionString)
            Me.IodbDataSet.dtTagList.Clear()
            da.Fill(Me.IodbDataSet.dtTagList)
    End Sub

    このFillのところで、
    「ConstraintException 制約を有効にできませんでした。1 つ以上の行に、Null か、一意でないか、または外部キー制約違反の値が含まれています。」
    のエラーが発生します。

    Clearができていないのでしょうか?
    問題点等、教えてください。
    2010年2月5日 5:51

回答

すべての返信

  • 外部キー制約について調べられることをお勧めします。簡単に説明すれば以下の通りです。
    テーブルAとテーブルBがあります。

    テーブルA
    id      name
    --------------
    1        hoge
    2        fuga
    3        moge

    テーブルB
    tableAid    age
    -----------------
    2               30
    3               35

    テーブルBのtableAidは、テーブルAのidのどれかと必ず一致するものとします。これが外部キー制約です。
    この時、テーブルAの2 fugaを削除してしまうと上記の前提が崩れてしまいます。これが外部キー制約違反です。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2010年2月5日 6:42
    モデレータ
  • 返信ありがとうございます。
    でも、外部参照はないのです。

    2010年2月5日 9:12
  • う~ん、こういう話なのでしょうか?

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=27998&forum=7

    以下のように DataSet.EnforceConstraints プロパティを False にするとどうなります?

    Public Sub LoadDatabaseIND()
            Dim fs As String = ""
            Dim sql As String
            sql = "SELECT * FROM tbl_tag WHERE tag_type = 'IND' "
            Dim da As New System.Data.Odbc.OdbcDataAdapter(sql, My.Settings.iodbConnectionString)        
            Me.IodbDataSet.dtTagList.Clear()
            Me.IodbDataSet.EnforceConstraints = False ' ここに追加してみた
            da.Fill(Me.IodbDataSet.dtTagList)
    End Sub
    2010年2月5日 9:47
    モデレータ
  • 返信ありがとうございます。

    EnforceConstraints をFalse にするとエラーはでなくなりますが、
    WHERE句が効いていないのです(つまりSELECTできてないみたい)。

    2010年2月5日 11:40
  • > Null か、一意でないか、または外部キー制約違反の値

    Fill する前に Clear しているので「一意でない」ということはないはずで、「外部キー制約
    違反」もないとのことですので、残るは「Null」が疑わしいということになります。

    IodbDataSet.dtTagList のどれかの行で DataColumn.AllowDBNull プロパティが
     false に設定されていて(デフォルトは ture)、そこに null を Fill しようとしたということ
    はないでしょうか?

    ---------------------------------------
    追伸です。

    試してみましたが、DataColumn.AllowDBNull 違反では ConstraintException は
    スローされなかったです。(汗)

    う~ん、原因がわかりません。もう少し情報を提供できませんか。

    2010年2月6日 10:27
  • 返信、ありがとうございます。

    NULL制約もないんです。。。主キーしか設定していません。
    月曜日に、もう少し調べてみます。

    2010年2月6日 13:21
  • > NULL制約もないんです。。。主キーしか設定していません。

    Visual Studio 2008 ドキュメントの DbDataAdapter.Fill メソッド (DataSet) の説明に
    よると、

    "主キー情報が存在する場合、重複行は、DataSet に対応する DataTable 内に 1 つだ
    け現れるように調整されます。"

    とのことなので、「主キーしか設定していません」ということですと、Clear しなくても Fill の
    ところで ConstraintException がスローされるようなことはないはずですが・・・

    やはり外部キー制約が怪しそうです。テーブルのスキーマなどもう一度見直してみてはい
    かがでしょう。

    ところで、OdbcDataAdapter を使っておられますが、データベースは何ですか?

    2010年2月7日 7:27
  • 返信ありがとうございます。

    もう一度確認してみます。
    データベースはPostgreSQLです。

    2010年2月7日 19:43
  • Me.IodbDataSet.dtTagList をビュワーで見たところ、ClearもFillも意図した結果が
    入っておりました。

    開発途中で、テーブルの列名/型定義の変えた為、Null 値がありえる列に AllowDBNull = False が
    指定されている部分があり、Trueにする事により、エラーは発生しなくなりました。
    ありがとうございました。

    しかし、問題が。。。。。
    Me.IodbDataSet.dtTagList には、SELECT * FROM tbl_tag WHERE tag_type = 'IND' に従い
    選択された行のみが存在しますが、画面では選択された行以外の全ての行が表示されてしまう
    のです。バインディングナビゲータコントロールの総レコード数も選択にかかわらない総数に
    なっていて、実際に表示できてしまうのです。

    画面に反映させる為には、何か抜けがあるのでしょうか?



    2010年2月8日 12:38
  • > Me.IodbDataSet.dtTagList には、SELECT * FROM tbl_tag WHERE tag_type = 'IND'
    > に従い選択された行のみが存在しますが、画面では選択された行以外の全ての行が
    > 表示されてしまうのです。

    それだけの情報では、何をどのように画面に表示しているのか、どこに問題があるの
    か見当もつかず、コメントしようがありません。

    差し支えなければ、問題を再現できる最小限のコードに絞って、ここにアップしてい
    ただけると、問題の解決のお役に立てるかもしれません。

    2010年2月8日 13:34
  • コードは以下の通りです。

    Public Class frmIND

        Private Sub Tbl_tagBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Me.Validate()
            Me.Tbl_tagBindingSource.EndEdit()
            Me.Tbl_tagTableAdapter.Update(Me.IodbDataSet.tbl_tag)
        End Sub

        Private Sub Tbl_tagBindingNavigatorSaveItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Me.Validate()
            Me.Tbl_tagBindingSource.EndEdit()
            Me.Tbl_tagTableAdapter.Update(Me.IodbDataSet.tbl_tag)
        End Sub

        Private Sub Tbl_tagBindingNavigatorSaveItem_Click_2(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tbl_tagBindingNavigatorSaveItem.Click
            Me.Validate()
            Me.Tbl_tagBindingSource.EndEdit()
            Me.Tbl_tagTableAdapter.Update(Me.IodbDataSet.tbl_tag)
        End Sub

        Private Sub frmIND_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            LoadDatabaseIND()
        End Sub

        Public Sub LoadDatabaseIND()
            Dim fs As String = ""
            Dim sql As String
            sql = "SELECT * FROM tbl_tag WHERE tag_type = 'IND' "
            Dim da As New System.Data.Odbc.OdbcDataAdapter(sql, My.Settings.iodbConnectionString)
            Me.IodbDataSet.dtTagList.Clear()
            da.Fill(Me.IodbDataSet.dtTagList)
        End Sub

    End Class

    2010年2月8日 23:31
  • クリアできない件については、下記の掲示板にて解決していますよね?
    マルチポストするなとは言いませんが、マルチポストした先での解決状況などを共有するように努めないと解決で時間がかかってしまうと思います。


    http://bbs.wankuma.com/index.cgi?mode=al2&namber=46580&page=0#10
    http://blogs.wankuma.com/hatsune/
    2010年2月9日 0:22
  • Clear の件は、↑で報告しています。
    2010年2月9日 0:26
  • 解決しました。お騒がせいたしました。

    2010年2月9日 5:26
  • >  解決しました。お騒がせいたしました。

    何故ダメだったかを書いて、このスレッドをクローズしていただけませんか?
    2010年2月9日 14:41
  • dtTaglist が問題で、tbl_tag に変更しました。 
    • 回答としてマーク すりーぷ 2010年2月9日 14:49
    2010年2月9日 14:49
  • > dtTaglist が問題で、tbl_tag に変更しました。 

    意味が分かりませんが。
    2010年2月9日 14:50
  • Me.IodbDataSet.dtTagList.Clear()
    da.Fill(Me.IodbDataSet.dtTagList)

    この2行を

    Me.IodbDataSet.tbl_tag.Clear()
    da.Fill(Me.IodbDataSet.tbl_tag)

    にしてみたのです。
    2010年2月9日 20:13