トップ回答者
データテーブルがクリアできない?

質問
-
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ができていないのでしょうか?
問題点等、教えてください。
回答
すべての返信
-
外部キー制約について調べられることをお勧めします。簡単に説明すれば以下の通りです。
テーブル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/ -
う~ん、こういう話なのでしょうか?
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
-
> Null か、一意でないか、または外部キー制約違反の値
Fill する前に Clear しているので「一意でない」ということはないはずで、「外部キー制約
違反」もないとのことですので、残るは「Null」が疑わしいということになります。IodbDataSet.dtTagList のどれかの行で DataColumn.AllowDBNull プロパティが
false に設定されていて(デフォルトは ture)、そこに null を Fill しようとしたということ
はないでしょうか?---------------------------------------
追伸です。試してみましたが、DataColumn.AllowDBNull 違反では ConstraintException は
スローされなかったです。(汗)う~ん、原因がわかりません。もう少し情報を提供できませんか。
-
> NULL制約もないんです。。。主キーしか設定していません。
Visual Studio 2008 ドキュメントの DbDataAdapter.Fill メソッド (DataSet) の説明に
よると、"主キー情報が存在する場合、重複行は、DataSet に対応する DataTable 内に 1 つだ
け現れるように調整されます。"とのことなので、「主キーしか設定していません」ということですと、Clear しなくても Fill の
ところで ConstraintException がスローされるようなことはないはずですが・・・やはり外部キー制約が怪しそうです。テーブルのスキーマなどもう一度見直してみてはい
かがでしょう。ところで、OdbcDataAdapter を使っておられますが、データベースは何ですか?
-
Me.IodbDataSet.dtTagList をビュワーで見たところ、ClearもFillも意図した結果が
入っておりました。
開発途中で、テーブルの列名/型定義の変えた為、Null 値がありえる列に AllowDBNull = False が
指定されている部分があり、Trueにする事により、エラーは発生しなくなりました。
ありがとうございました。
しかし、問題が。。。。。
Me.IodbDataSet.dtTagList には、SELECT * FROM tbl_tag WHERE tag_type = 'IND' に従い
選択された行のみが存在しますが、画面では選択された行以外の全ての行が表示されてしまう
のです。バインディングナビゲータコントロールの総レコード数も選択にかかわらない総数に
なっていて、実際に表示できてしまうのです。
画面に反映させる為には、何か抜けがあるのでしょうか? -
コードは以下の通りです。
Public Class frmINDPrivate 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 SubPrivate 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 SubPrivate 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 SubPrivate Sub frmIND_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
LoadDatabaseIND()
End SubPublic 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 SubEnd Class