DBGridで選択しているところを削除


優菜  2010-02-04 05:55:48  No: 37430

Delphi5を使って、DBGridでdelete処理をしようとしています。データベースのテーブルのデータを削除したいのですが、テーブルのデータには一切プライマリーキがかかってなく、データが重複している状態です。そのテーブルのデータを1件だけ削除する処理を試みているのですが、重複をゆるなさいIDがないため、苦労しています。

クエリを使って、
  with QRY1 do
   CLOSE;
   SQL.CLEAR;
   SLQ.ADD('DELETE FROM TABLE WHERE' = SELECTEDROWS);
   EXECSQL;(これは、コンパイルエラーになりました)

のような感じで、DBGRIDで指定している行1件を削除する方法はないのでしょうか?もし知っていましたら、教えてもらえませんか?


HOta  2010-02-04 06:06:34  No: 37431

TDBGridのTDatasetがTQueryの場合は、TUpdateSQLを使い
DBGrid1.Datasorce.dataset.Delete;
で削除できます。


優菜  2010-02-04 08:02:18  No: 37432

そうすると、TQueryのTUpdateSQLを使わないと、私が実行しようとしていることは、できないということなのでしょうか(where句でDBGridを指定)?


Mr.XRAY  2010-02-04 09:18:51  No: 37433

Mr.XRAYです.

クエリーでも削除のSQL文を書くことが可能ですが,これは一意のID等がある場合,
それをDBGridで選択しているDataSetから取得してWHERE句に指定することになります.
したかって,今回の場合,「重複をゆるなさいIDがないため」ということですので,できません.

>(where句でDBGridを指定)?

できません.SQLのWHERE句データセットの条件指定句(文)です,
データベース用のコントロールのプロパティ等を使用することはできません.

データベースと,クエリー用のコンポーネントにもよりますが,
(注意 : クエリーは基本的にデータベースが提供する機能です.どこかのスレッドに
「DelphiのSQL文」という語句がありましたが,そういうのはありません)

  TQuery.DeleteRecords(arCurrent);

のように,現在選択中のデータを削除することもできます.
arCurrentは「現在の」意味です.

データベースの表を設計する際は,必ず一意の値を持つフィールドを定義しておくことが重要ですね.


ぽむぽむ  2010-02-04 17:54:07  No: 37434

一意なキーがなければ、全ての列を指定してしまえばいいんじゃまいか?

  QRY1.SQL.CLEAR;
  QRY1.SQL.ADD('DELETE FROM TABLE名');
  QRY1.SQL.ADD('WHERE');
  for i := 0 to QRY1.FieldCount - 1 do begin
    if QRY1.Fields[i].DataType = ftString then
      QRY1.SQL.ADD(Fields[i].FieldName + '=''' + Fields[i].AsString + '''')
    else
      QRY1.SQL.ADD(Fields[i].FieldName + '=' + Fields[i].AsString + ');
    if i > 0 then  QRY1.SQL.ADD('AND');
  end;

やったことないことだし、はずしてるかな・・・


Kenny  2010-02-04 18:18:08  No: 37435

ぽむぽむさんの案だと、全てのフィールドが完全に一致する複数のデータがあった場合、
一致した全部が消えないですか?
間違えて二重入力したときに、片方だけを消去することはできない、という条件になるような。


maru3  2010-02-04 18:56:20  No: 37436

ユニークなIDを持つフィールドを作成するのが早道ではないですか?
例えば、別名で同様の内容でかつ、IDフィールドを持つテーブルを作り、
IDフィールドをカウンター型(DBにこの型が無ければ自作)にして、
ちまちまと、1行ずつUPDATEしていきます。
データが多いと時間はかかると思いますが・・・・。
回り道のほうが早いような、また今後のために良いような気がします。


ぽむぽむ  2010-02-04 20:41:20  No: 37437

Kenny さん
> 間違えて二重入力したときに、片方だけを消去することはできない、という条件になるような
その通りですわ、全く思いつきもしませんでした。
なにか憑かれているようです(違

maru3さんの、ユニークになる列を作るのが手っ取り早い方法だと思います。
Oracle・・・だったら、列追加が面倒なので・・・
1)ユニークになる列がある、別の仮テーブルを作る
2)仮テーブルに全てインサート
3)仮テーブルで不要レコードを削除する
4)元テーブルを削除する
5)仮テーブルを本テーブルに置き換える

元のテーブルの構造を変えることができないということであれば、
4)元テーブルのデータを削除
5)仮テーブルから元テーブルに複写


優奈  2010-02-06 10:09:04  No: 37438

Mr. XRAYさん、TQuery.DeleteRecords(arCurrent);
で、現在のレコードを削除できるとのことですが、
buttonのonclickのところに、
datamodule1.Query1.DeleteRecords(arCurrent);と記述したら、
認識ができないというコンパイルエラーになってしまいました。
これは、このコードの前後に別のコードを記述しないとそのままでは使用することができないのでしょうか?

HOTAさん、TUpdateSQL上になにかコードを書く必要はあるのでしょうか?DBGrid1.Datasorce.dataset.Delete;を、buttononclickなどに、記述すればいいのですか?TUpdateSQLは、今までに全く使ったことがなかったので、確認させていただきました。


Kenny  2010-02-06 20:25:08  No: 37439

TUpdateSQLを貼り付けた後、TQueryのUpdateObjectにUpdateSQLを指定してください。
あとはプロパティ設定が済んでいるのなら、ボタンクリックなどに
DBGridなんちゃら.DataSource.DataSet.Delete
と書くだけです。

DeleteRecords()は、ADOQueryの場合ですかね?  Del7のTQueryでは使えないようです。


HOta  2010-02-06 20:33:12  No: 37440

使用中のDatasetが編集可能でないと、削除はできません。TUpdateSQLは、例えば複数のテーブルからのSQL文の場合は、どのテーブルに対して更新するかわかりませんから、対象を指定するためのものです。
Datasetが何かわかりませんが、TQueryを使っていると仮定すると、TQueryのRequestLiveをTrueにしてください。これで削除はできると思います。
複数のテーブルからのSQL文の場合は、TUpdateSQLを更新するテーブルの数だけ設定して、TQueryのUpdateObjectに;区切りで設定します。それぞれのTUpdateSQL右クリックから設定します。


Mr.XRAY  2010-02-07 02:03:29  No: 37441

Mr.XRAYです.
関係レスのみです.

>datamodule1.Query1.DeleteRecords(arCurrent);と記述したら、
>認識ができないというコンパイルエラーになってしまいました。

今,以下で確認しました.削除できています.

Windows XP(SP3) + Delphi6(UP2) Pro + Oracle8i 8.1.6 + TADOQuery
Windows XP(SP3) + Delphi6(UP2) Pro + JET4.0(mdb) + TADOQuery

コード補完機能というのをご存知でしょうか?
http://mrxray.on.coocan.jp/Others/A_IDETechnique.htm#05

Query1.までタイプして,候補にDeleteRecordsが表示されなければ,そのQueryコンポーネント
では使用できません.

>データベースと,クエリー用のコンポーネントにもよりますが,

と書いたのはそういう意味です.
Delphi5というのは記述がありますが,その他は不明ですのでこう書きました.
ご了承ください.


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加