vb2008からデータベースのNULL禁止項目を含む変更方法

このQ&Aのポイント
  • vb2008とSQLServer2008Expressを勉強しております。
  • データベース「tblTest」のDataGridViewからNULLを禁止された項目を含む変更方法について困っています。
  • NoとCity両方を変更する処理について、For Each Rowを使用して1行ずつ処理をかける方法を教えていただけませんか?
回答を見る
  • ベストアンサー

vb2008からデータベースのNULL禁止項目を含む変更したい

vb2008とSQLServer2008Expressを勉強しております。 データベース「tblTest」を作成し、DataGridViewからNULLを禁止された項目を含む変更を行う処理で困っています。 tblTestの内容は No|City ---------- 0 |Tokyo 1 |Osaka 2 |Fukuoka 3 |Nagoya としており、NoをNULL禁止にしております。 SQLDataAdapterを使用して UpdateCommand、InsertCommand、DeleteCommandの設定、実行はうまくいきました。 困っている点は、 No |City ---------- 0 |Tokyo 1 |Osaka 2 |Fukuoka 3 |Nagoya  ←ここを No |City ---------- 0 |Tokyo 1 |Osaka 2 |Fukuoka 4 |Hokkaido ←この様に変更したい NoとCity両方を変更するような処理をしたい場合についてです。 DataGridView上では値の変更ですが、 処理的にはInsertCommandとDeleteCommandが一緒に実行されるような気がします。 このような場合、どのような処理を行えばいいのでしょうか? For Each Row As DataRow In Table.Rows で1行ずつ処理をかけるのでしょうか? お分かりの方、アドバイスだけでもよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.2

>TransactionScopeについてしらべてみました。 例外が発生したときに、変更を元に戻すものであると理解できました。 基本的にはそのとおりですが、 解釈としては、 複数のクエリの同時実行を保障してくれるものと考えてください。 AとBのクエリを同時に実行したい時に、 Aは成功したが、Bは失敗した場合、テーブル間の整合性を確保できなくなる場合に使用します。 例 商品Aを販売した場合 クエリA:商品テーブルからAの個数を1個減らす。 クエリB:売り上げテーブルにAの販売伝票を登録する。 この場合はどちらも同時に行われ、かつ両方のクエリが確実に成功しなければ整合性を保てませんね。 こういう場合に使用します。 本題に戻ります。 0 |Tokyo 1 |Osaka 2 |Fukuoka 3 |Nagoya  ←ここを No |City ---------- 0 |Tokyo 1 |Osaka 2 |Fukuoka 4 |Hokkaido ←この様に変更したい とのことでした、 No,Cityを同時に変更したいわけですから、やり方は2種類です。 1.Updateで同時に変更する。 2.一回削除して、再度追加する。 1.の場合は、 SQL = "UPDATE tblTest SET City = @city WHERE No = @no" では、Cityにしか値をセットしていないので、Noは変更されませんので、 SQL = "UPDATE tblTest SET No = @no, City = @city WHERE No = @no" としなければいけません。 2.の場合は、 "DELETE FROM tblTest WHERE No = @no " を実行後、 "INSERT INTO tblTest (No, City) VALUES (@no, @city)" を実行すればよいのです。 ただし、同時に実行したいので、両方をトランザクションスコープ内で行うことが必要です。

tree_002
質問者

お礼

おかげさまで、何十行もの余分な処理が削除できました。 お時間を頂き申し訳ありませんでした。 ありがとうございます。

tree_002
質問者

補足

AKARI0418様、ご回答ありがとうございます。 >1.Updateで同時に変更する。 >2.一回削除して、再度追加する。 おかげさまで、1番の方法を利用し解決できました。 また、2番の方法でも正しく処理が行われました。 ありがとうございます。 >AとBのクエリを同時に実行したい時に、 Aは成功したが、Bは失敗した場合、テーブル間の整合性を確保できなくなる場合に使用します。 テスト環境でご指摘の現象が頻発しておりました。 こういった場合に使えばいいのですね。 ありがとうございます。 1ヶ月近く悩んでいたことが解決できました。 本当にうれしいです。ありがとうございます。

その他の回答 (1)

  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.1

TransactionScopeを使用して、 削除と追加を同時に行うようにします。 まずInsert文で、 4 |Hokkaido  を追加し。 その後、 3 |Nagoya  をDeleteします。 TransactionScopeを用いて、 片側のみ行われることを避けます。

tree_002
質問者

補足

AKARI0418様、ご回答ありがとうございます。 TransactionScopeについてしらべてみました。 例外が発生したときに、変更を元に戻すものであると理解できました。 現在、Form_Loadの中にてSelect,Insert,Update,Deleteコマンドを設定しております。  SQL = "SELECT * FROM tblTest"  command = New SqlCommand(SQL, connection)  dataAdapter.SelectCommand = command  SQL = "INSERT INTO tblTest (No, City) VALUES (@no, @city)"  command = New SqlCommand(SQL, Connection)  command.Parameters.Add("@no", SqlDbType.Int, 32, "No")  command.Parameters.Add("@city", SqlDbType.Text, 32, "City")  dataAdapter.InsertCommand = command  SQL = "UPDATE tblTest SET City = @city WHERE No = @no"  command = New SqlCommand(SQL, connection)  command.Parameters.Add("@city", SqlDbType.Text, 32, "City")  Dim parameter As SqlParameter = command.Parameters.Add("@no", SqlDbType.Int, 32, "No")  parameter.SourceVersion = DataRowVersion.Original  dataAdapter.UpdateCommand = command  SQL = "DELETE FROM tblTest WHERE No = @no "  command = New SqlCommand(SQL, connection)  command.Parameters.Add("@no", SqlDbType.Int, 32, "No")  dataAdapter.DeleteCommand = command これを、ボタン押下にて  myDataAdapter.Update(myDataAdapter.Update(myDataSet.Tables(0)) を実行し、DataAdapterの内容をデータベースに反映させております。 これをご指摘頂いたTransactionScopeを用いて  Using scope As New TransactionScope()   myDataAdapter.Update(myDataSet.Tables(0))   scope.Complete()  End Using としてみましたが、 「No」は更新されず、 「City」のみ更新されました。 これはUpdateコマンドしか実行されなかったと推測しました。 これを、ご指摘頂いた削除と追加を同時に行うにはどうすればよいのでしょうか? もしくは、Form_Load内の各種Commandの記述がおかしいのでしょうか? よろしくお願いいたします。

関連するQ&A

  • どのようなSQL文を発行したら実現可能でしょうか?

    NewIDという行を作成しそのすべての行は"pro"+"ID"にしたいのですが出来ますか? NewIDという行の作成は出来ました ID | City New ID| ID | City -----------      -------------------- 3456 | Tokyo pro3456 |3456 |Tokyo 1234 | Osaka ⇒   pro1234 |1234 |Osaka 0123 | Nagoya pro0123 |0123 | Nagoya

  • 変数の一致条件がたくさんあるときの判定の書き方

    変数の一致条件がたくさんあるときの判定の書き方を教えてください <例> $areaが、下記の条件判定 tokyo osaka nagoya 現状では、下記のように書いているのですが、 今後、この条件が増えてくる可能性があるので、 そうしたとき、もっとスマートに書きたいです if (($area=='tokyo') || ($area=='osaka') || ($area=='nagoya')) {  処理; }

    • ベストアンサー
    • PHP
  • 複数フォルダの移動バッチ

    PCにある複数フォルダ(2000フォルダ)を別PCに移動させたいのですが、いいバッチはありませんでしょうか? 環境はXPです。 robocopyのコマンドも使えるようにはなっています。 ■元PC C:\abc\tokyo\0000\ C:\abc\tokyo\0022\ C:\abc\osaka\0000\ C:\abc\osaka\0123\ C:\abc\nagoya\0000\ C:\abc\nagoya\0568\ 等などのフォルダがあります。 各数字のフォルダ以下にファイルがあります。 この中で指定したフォルダを移動させたいのです。 例: C:\abc\tokyo\0000\ C:\abc\osaka\0123\ C:\abc\nagoya\0568\ を D:\backup\tokyo\0000\ D:\backup\osaka\0123\ D:\backup\nagoya\0568\ という風に移動させたいです。 xcpyで指定数書いて実行後、mkdirを流すしかないでしょうか? 例:xcopy /E C:\abc\tokyo\0000 D:\backup\tokyo\0000\   rmdir /Q /S C:\abc\tokyo\0000 みたいに2000行程書く以外に何か方法はありますでしょうか?

  • Column名を変えた時のUpdate文の書き方

    よろしくお願い致します。 VB2010とSQLServer2008でデータベースの勉強をしております。 DataAdapterを使用し、SelectCommand,UpdateCommandを設定、 それをDataGridViewに表示させています。 Column名とデータをSelectComanndの「AS」で変更した場合の Update文の「CASE」の書き方?で混乱しております。 データベース Test1 No Sex ------ 1 1 2 2 3 0 DataGridViewの表示 No 性別 ------- 1 男 2 女 3 ? データベース Test1をDataGridViewに表示 その際、「Sex」を1=男, 2=女, 0=?と表示させています 同時に、Column名を「性別」に変えました SelectCommandでSQL文を以下のように設定しました SELECT No, CASE Sex WHEN 1 THEN '男'                WHEN 2 THEN '女'                ELSE '?'         END AS 性別 FROM Test1 これは希望通りに表示されました UpdateCommandでSQL文を以下のように設定しました。 UPDATE Test3 SET Sex = CASE @sex WHEN '男' THEN 1                         WHEN '女' THEN 2                         ELSE 0                 END WHERE No = @no SQLDataAapter.UpdateCommand = New SqlCommand(SQL, myConnection) SQLDataAapter.UpdateCommand.Parameters.Add("@sex", SqlDbType.Int, 32, "Sex") SQLDataAapter.UpdateCommand.Parameters.Add("@no", SqlDbType.Int, 32, "No").SourceVersion = DataRowVersion.Original UPDATE文でCASEが使えることは検索して分かったのですが、 Columnの表示を変えた場合はどうしたらよいのでしょうか? なお、Select文、Update文ともに、「CASE」句を削除すれば正しく動作することは確認できました。 質問する場所を「データベース」と迷ったのですがこちらにしました。 ご指導のほど、よろしくお願い致します

  • VB2008、Insertのループをかけたいのですが・・・

    初の質問になりますが、よろしくお願いします。 現在、VB2008にて、DataGridViewに入力した内容を、Insertで登録処理をするという作業を行っているのですが、変わった現象が起きてしまうのです。 まず、ボタンクリックのイベントで、DataGridViewの内容を一行づつ取り込み、Insertのループを行うと言うものなのですが、 DataGridViewにある列は、'日付','出勤時間',退社時間','~~と続くのですが、日付だけしか一行づつ取り込めず、それ以外の列項目は、値の入っている列までしか取り込めないんです。 たとえば、二行目まで値を入れ、三行目からはすべてのCellをNullの状態にしてInsertのループをかけると、二行目にしか入らない値が、三行目以降まで続いてしまうんです。これってどういうことでしょうか、、、ちなみに日付だけはきちんとInsertされるのです。どなたかお分かりになる方いらっしゃらないでしょうか。 ちなみにこれがソースです。 For r As DataGridViewRow in DataGridView1.Rows 日付 = DataGridView1(0, r.Index).Value If IsDBNull (DataGridView1(9, r.Index).Value) = False Then 出勤時間 = DataGridView1(9, r.Index).Value Else If IsDBNull(DataGridView1(5. r.Index).Value) = False Then 出勤時間 = "0" End If '列が多いので、省略します。 'ここからInsert sql = "Insert into Time Seet" sql &= "Values (" sql &= "'" & 日付 & "'" : : Next r という形です。列が長いので、だいぶ省略しましたので伝わりにくいかと思いますが、よろしくお願いします。 ちなみに他のサイトでは、 ループの外側でパラメータクエリを作成して、ループの中ではパラメータの設定とSQLの実行のみにすればよいです。 と言われましたが、パラメータクエリというのがイマイチ理解できなかったので・・・ できればそれらに関する情報や考え方なども教えてくださるとうれしいのですが・・・よろしくお願いします。

  • 成長した地名にもとずく呼称について。

    Tokyoite, Chicagoan, New Yorkerなどとありますが、 他の主な都市のNativeな人の呼称が知りたいです。 特に、San Francsico, Los Angels, Oslo, Berlin, Pari, Roma, まあ、主な首都やビジネス・シティーのNativeな呼称が知りたいです。ただ、驚いたのは、Tokyoite, Tokyojin, Edokkoは、定義が違うんですね。日本の主な都市の成長した都市人の呼称も知りたいです。Kyoto, Nagoya, Osaka, Fukuoka, Sendai, Kobe, Yokohamaですね。特に北欧の主な都市で成長した人の呼称が知りたいですね。マリア・シャラポワは、ロシア人ですが、事実上は、アメリカ人なんていう問題もありますが。よろしくお願いします。

  • .net データベースへ反映する方法

    <環境> 言語:Microsoft Visual Studio 2008 データベース:SQL Server 2005 非接続型のデータアクセスです。 以前同じ質問をさせていただいたのですが、解決できなかったため、再度投稿させていただきました。 <質問> DataGridViewにデータを表示し、登録、修正、削除を行った後、 更新ボタンを押下でDataGridViewの内容をデータベース(SQLServer)に反映したいのですが、エラーとなり反映できません。 http://japan.internet.com/developer/20070522/26.html を参考にしているのですが、四苦八苦。全然前に進めない状態です。 自作したコードを下記の通りです。いったいどこを直せばよろしいでしょうか?どなたかアドバイスよろしくお願いします。 <エラー>---------------------------------------------------------- "System.ArgumentNullException: 値を Null にすることはできません。  パラメータ名: dataTable  場所 System.Data.Common.DbDataAdapter.Update(DataTable dataTable) -------------------------------------------------------------------- Private Sub frmDataGridViewTest_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load   Dim strsql As String   Call DBConnect() 'DB接続   strsql = "SELECT ID, 名称, 型式 FROM ATBL ORDER BY ID"   Dim comm As SqlCommand = New SqlCommand(strsql, Con)   Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm)   dataadapter.MissingSchemaAction = MissingSchemaAction.AddWithKey   Dim ds As DataSet = New DataSet()   dataadapter.Fill(ds, "テーブル")   dgrview.DataSource = ds   dgrview.DataMember = "テーブル"   Call Disconnect() 'DB切断 End Sub Private Sub BTN_更新_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_更新.Click   Dim strsql As String   Call DBConnect() 'DB接続   strsql = "SELECT ID, 名称, 型式 FROM ATBL ORDER BY ID"   Dim comm As SqlCommand = New SqlCommand(strsql, Con)   Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm)   dataadapter.MissingSchemaAction = MissingSchemaAction.AddWithKey   dataadapter.Fill(ds, "テーブル")   Dim dt As DataTable = ds.Tables("テーブル")   '<<<DataGridViewコントロールでの変更をデータベースに戻す>>>   Dim sqlCmdBuilder As New SqlCommandBuilder(dataadapter)   sqlCmdBuilder.GetUpdateCommand()   dataadapter.Update(ds.Tables("テーブル"))   Call Disconnect() 'DB切断 End Sub

  • VB DB更新時にパラメーターへ値のセット

    データベースの更新についてご指導下さい。 VB2010からSQLサーバーのデータベースに接続しております。 dataAdapter.Updateによりデータベースを更新する際の パラメーターへ値をセットする方法を教えて下さい。 テーブル名Test Code Name ------------ A   Suzuki 希望する処理 テキストボックスに入力された名前に変更 例) Suzuki → Yamada ○フォームの変数として定義 Dim dataAdapter As New SqlDataAdapter Dim dataSet As New DataSet ○FormLoad時にSelectCommandとUpdateCommandを設定 Dim SQL As String = "" Dim command As SqlCommand Dim connection As SqlConnection = New SqlConnection(~) SQL = "SELECT * FROM Test WHERE Code = @code " command = New SqlCommand(SQL, connection) dataAdapter.SelectCommand = command dataAdapter.SelectCommand.Parameters.Add("@code", SqlDbType.Char) SQL = "UPDATE Test SET Name = @name WHERE Code = @code" command = New SqlCommand(SQL, connection) dataAdapter.UpdateCommand = command dataAdapter.UpdateCommand.Parameters.Add("@code", SqlDbType.Char) dataAdapter.UpdateCommand.Parameters.Add("@name", SqlDbType.Text, 50) ○データ表示時にはこれで表示されました。 dataAdapter.SelectCommand.Parameters.Item("@code").Value = ComboBoxCode.text dataAdapter.Fill(dataSet) ○このSelectCommandを参考にこのように書いて見たのですが更新されません。 dataAdapter.UpdateCommand.Parameters.Item("@code").Value = ComboBoxCode.Text dataAdapter.UpdateCommand.Parameters.Item("@name").Value = TextBoxName.Text dataAdapter.Update(dataSet) どのようにしたら実行時にパラメーター化したところへデータをセットできるのでしょうか? データセットに値が入っていないのでは?と予想したのですが…。

  • DataGridViewについて

    Fom1のDataGridViewから選択した行のデータをForm2のDataGridViewに渡し、Form2で編集しFom1に反映せると、どの行のデータも1行目に入ってしまいます。 どのようなコードで解決できますか? 【Form1】 private void DataGridView1_SelectedRowsDoubleClick(Object sender, MouseEventArgs e) { // Form2を作成し、親フォームとしてForm1を設定する Form2 f2 = new Form2(); f2.Owner = this; // 親フォームを設定 // 選択行のデータを渡す f2.SetRowData(dataGridView1.SelectedRows, dataGridView1); // Form2を表示する f2.Show(); } /// <summary> /// 選択行のデータを更新するメソッド public void UpdateSelectedRowData(int rowIndex, string editedData1, string editedData2, string editedData3) { // データソースが DataTable の場合のみ処理を実行する if (dataGridView1.DataSource is DataTable dt && dt.Rows.Count > rowIndex) { // データ行を取得する DataRow dataRow = dt.Rows[rowIndex]; // 編集データを新しいデータ行にセットする dataRow["date"] = editedData1; dataRow["name"] = editedData2; dataRow["week"] = editedData3; } } } } 【Form2】 public void SetRowData(DataGridViewSelectedRowCollection rows, DataGridView dataGridView)  { //データテーブルの作成 DataTable dt = createData(); foreach (DataGridViewRow r in rows) { //1列目~3列目を取り出す string s1 = r.Cells[1].Value.ToString(); // 日付 string s2 = r.Cells[2].Value.ToString(); // 名前 string s3 = r.Cells[3].Value.ToString(); // 曜日 dt.Rows.Add("2023年", s1, s2, s3); //日付順に昇順に表示する dt.DefaultView.Sort = "日付 ASC"; } //一覧を表示する dataGridViewDisp2(dt); } // 編集後のデータを保持するためのプロパティ public string EditedData1 { get; set; } public string EditedData2 { get; set; } public string EditedData3 { get; set; } /// 更新ボタンの処理 private void savebtn_Click(object sender, EventArgs e) { // 親フォーム Form1 をForm1に指定する Form1 form1 = this.Owner as Form1; if (form1 != null) { // Form1のDataGridViewのデータソースを取得する DataTable dt = form1.dataGridView1.DataSource as DataTable; if (dt != null) { // dataGridView2の各行を処理する foreach (DataGridViewRow row in dataGridView2.Rows) { // 新規行はスキップする if (row.IsNewRow) continue; // 編集されたデータを取得する string editedData1 = row.Cells[1].Value.ToString(); string editedData2 = row.Cells[2].Value.ToString(); string editedData3 = row.Cells[3].Value.ToString(); // 選択された行のインデックスを取得する int rowIndex = row.Index; // 親フォーム Form1 の UpdateSelectedRowData メソッドを呼び出す form1.UpdateSelectedRowData(rowIndex, editedData1, editedData2, editedData3); } } } // 現在のフォームを閉じる this.Close(); } } }

  • CakePHP3 belongsTo NULL登録

    CakePHP3.0 を使用して、顧客情報を登録するアプリケーションを作成しています。 顧客情報には言語カラムがあり、外部の言語テーブルのコードを参照しています。 顧客情報の言語カラムはNULLを許容します。 DB [Table] client_entities | language_code1 | char(2) | NULL YES | MUL | | language_code2 | char(2) | NULL YES | MUL | | language_code3 | char(2) | NULL YES | MUL | | language_code4 | char(2) | NULL YES | MUL | | language_code5 | char(2) | NULL YES | MUL | | language_code6 | char(2) | NULL YES | MUL | [Table] languages | id | int(11) | NULL NO | PRI | | code | char(2) | NULL NO | UNI | CakePHPでは、Tableにアソシエーションの定義を追加しました。 (Controllerのindex()にも設定を追加していますが、edit()、update()は未変更です) ClientEntitiesTable public function initialize(array $config) { $this->belongsTo('Languages', [ 'foreignKey' => 'language_code1', 'bindingKey' => 'code', 'joinType' => 'LEFT' ]); ..... continue } LanguagesTable public function initialize(array $config) { $this->hasMany('ClientEntities', [ 'foreignKey' => 'language_code1', 'bindingKey' => 'code' ]); ..... continue } この状態で、顧客情報の登録・更新処理において、言語カラム未設定でsubmitすると、 NULLの状態で送られた情報が内部で空文字''に変換されてしまいDBの参照整合性エラーが発生してしまいます。 Error情報 Error: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`cir`.`client_entities`, CONSTRAINT `client_entities_ibfk_7` FOREIGN KEY (`language_code2`) REFERENCES `languages` (`code`)) UPDATE client_entities SET language_code2 = :c0 WHERE id = :c1 解決方法として、TableクラスのbeforeSave()メソッドを内で空文字をNULLへ変換する処理を追加したのですが、 別のエラーが発生してしまいます。 Undefined variable: _SESSION [CORE\src\Network\Session.php, line 440] どなたか、CakePHPにて外部参照制約のついているカラムへNULLを登録する方法をご教授願えませんでしょうか?

    • 締切済み
    • PHP

専門家に質問してみよう