皆様こんにちは、
いつもお世話になっております。
下記の件、お手数ですがご回答頂ければ
幸いです。
開発環境は
Win2000, VC++6.0, MFC, SDI,MS SQL7.0の環境ですが
内容としましては、
データの更新したいといったものです。
CDatabase.ExecuteSQLを利用するとどうも処理が遅いようです。
そこで、CRecordsetのUpdateを使いたいのですが
rs.Open( CRecordset::dynaset,strSql,CRecordset::none);
とした場合において
dwConcurrency==SQL_CONCUR_READ_ONLY
となり、アペンドもアップデートもできない状態です。
どなたかご教授ください・
woodで検索してください
結構ソース載せてるよ
woodさん、
早速の御返答有難うございます。
本掲示板にて、WOODさんの
RESが多いことに驚きます。
また、いつもレスいただき有難うございます。
早速、確認してみましたが
どれが、それに該当するのか
残念ながら分かりませんでした。
現在、CanUpdateで引っかかり
CanUpdateを外すと読込専用と
エラーが出てしまうわけですが。
この手の対応方法は、
この掲示板にもよく出ている
アスキー出版のinside visual c++
に出てますでしょうか。
また、参考となるサイトがありましたら
お教え頂ければ幸いです。
何度もお手数をおかけいたします。
ビューによっては更新操作ができない場合もあります。
・ビューの1行がテーブルの1行に対応付けできない
・データベースが結合ビューの更新をサポートしていない
CString Sel_Txt;
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
UpdateData(TRUE);
CSSMMNMTNDoc* pDoc = GetDocument();
CSSMMNMTNSet mSet(&pDoc->m_database); ←レコードセットへ取得(コネクト済みデー
タベースポインタのセット
//
if(U_INPT_check() == FALSE){
// タイトル情報設定
mSet.m_strFilter.Format(COP_ID = %d ,m_COP_ID);
この条件値のデータは1件しか存在できないことを仮定しています
if(mSet.Open(CRecordset::dynaset,NULL)) { ←m_strFilterに沿ったデータの
取得
if(!mSet.IsEOF()) {
//既存データ 有りの場合
mSet.Edit(); // 変更を可能にする
mSet.m_ITEM_KB = 0;
}
else{
//既存データ なしの場合
mSet.AddNew(); //追加を可能にする
mSet.m_COP_ID = m_COP_ID;
UpdateData(TRUE);
}
if (mSet.CanUpdate()) {mSet.Update(); } 更新可能かどうかチェックして更新
ここ
}
mSet.Close
>CString Sel_Txt;
>if(U_INPT_check() == FALSE){
これは関係有りませんでしたね
woodさん
早速の御返答
有難うございます。
>>CSSMMNMTNSet mSet(&pDoc->m_database);
は
CSSMMNMTNSet mSet(&pDoc->m_pDatabase);
ですよね、環境の違いでしたらすいません。
>> mSet.m_strFilter.Format(COP_ID = %d ,m_COP_ID);
>> この条件値のデータは1件しか存在できないことを仮定しています
とありますが
複数の場合はどのように対応すればよろしいでしょうか。
関係ない行も含まれてますけどこんなことも出来ますよ
class CMARU10Doc : public CDocument
{
protected: // シリアライズ機能のみから作成します。
CMARU10Doc();
DECLARE_DYNCREATE(CMARU10Doc)
// アトリビュート
public:
CDatabase m_database;
これでコンパイル通っているからこれでやってます
-------------------------------------------------------
CXXXXView::CXDXDXD()
{
CMARU10Doc* pDoc = GetDocument();
CString m_BoxStr;
CCOSSet mCOS_Set(&pDoc->m_database);
CTANSet mTAN_Set(&pDoc->m_database);
UpdateData(TRUE);
m_CB_TOK_COS.GetLBText(m_CB_TOK_COS.GetCurSel(), m_BoxStr);
mCOS_Set.m_strFilter.Format(COS_RYAKU = '%s', m_BoxStr);
if(mCOS_Set.Open(CRecordset::dynaset,NULL)) {
if(!mCOS_Set.IsEOF()) {
ここ↓(前行のレコードセットで取得したデータが1件しかない前提で
mCOS_Set.m_COS_TANを次のレコードセットの検索キー項目へ代入
mTAN_Set.m_strFilter.Format(TAN_KANRI_KB = 2 and TAN_CD = %
d,mCOS_Set.m_COS_TAN);
if(mTAN_Set.Open(CRecordset::dynaset,NULL)) {
if(!mTAN_Set.IsEOF()) {
m_STC_TOK_TAN = mTAN_Set.m_TAN_NM;
}
}
mTAN_Set.Close();
}
----------------------------------------------------------------
>アスキー出版のinside visual c++
>に出てますでしょうか。
Ver 5.0
の825ページから882ページ
の内 850ページ 28.12など参考にしてますけど
Ver 4.0
にもあるよページ数違うけど
この本は5~6回通しで読んで見るといいよ
最初は小説の読書感覚で
後々、自分のやりたいことどの辺に書いてあるか分かるようになるよ
言葉の意味や関連項目の調べ方分からなくなったらMSDN
それでも分からないなら、ここで相談するといいよ
woodさん
ご返答ありがとうございます。
早速ためしてみました。
>> CCOSSet mCOS_Set(&pDoc->m_database);
>> CTANSet mTAN_Set(&pDoc->m_database);
は同じテーブルを参照しておりますでしょうか。
別のテーブルの場合はうまくいきましたが。。。
同一テーブルがうまくいきません。
>>CCOSSet mCOS_Set(&pDoc->m_database);
上記は複数レコード
>>CTANSet mTAN_Set(&pDoc->m_database);
は1レコードという認識でよろしいでしょうか。
>> m_STC_TOK_TAN = mTAN_Set.m_TAN_NM;
これは、データを退避しているのでしょうか。
どこで、EDIT、UPDATEをしますか。
自分なりにCloseの前にEdit,Updateをいれ
更新処理をしてみました
しかしながら前者、後者とも、読み込み専用のエラーになってしまいます。
OPEN時も例と同様の設定をしているのですが。。。
また、早速inside visual c++ Version5を購入しようと思います。
昨日、プログラミングVISUAL C++を購入したばかりですが。…
何とか、更新処理をうまく作動させたいと存じます。
ご教授お願いいたします。
>wood 2003/03/28(金) 07:01:30
ごめんなさい、単なる検索の例でした
今、会社ななので方法だけ
for文でIsEOF()になるまでやれば良いはずですけど
mSet.Edit(); // 変更を可能にする
mSet.m_ITEM_KB = 0;
最後に
if (mSet.CanUpdate()) {mSet.Update(); } 更新可能かどうかチェックして更新
更新件数によっては一度 Update();
後リクエリーして 処理し直す方が良いと思います
複数更新以前の問題のようですね
>しかしながら前者、後者とも、読み込み専用のエラーになってしまいます。
CDatabaseのOpenの記述はどうなっていますか
MSDN引用
------------------------------------------------------------------------------
virtual BOOL Open(
LPCTSTR lpszDSN,
BOOL bExclusive = FALSE,
BOOL bReadOnly = FALSE,
LPCTSTR lpszConnect = _T(ODBC;),
BOOL bUseCursorLib = TRUE
);
パラメータ
bReadOnly
接続を読み取り専用にする場合や、データ ソースの更新を禁止する場合は TRUE に設定
します。このメンバ関数に依存するすべてのレコードセットは、この属性を継承しま
す。既定値は FALSE です。
------------------------------------------------------------------------------
この「bReadOnly」設定間違っていませんか?
>CDatabase.ExecuteSQL
について
これはODBCエンジンを経由してSQLServer7にコマンドを送る
その後SQLServer7がコマンド翻訳作業を行う
簡単に言うとこんな感じになります
大量の内容の違うExecuteSQLがあった場合以前の翻訳結果は消去されます
保持される数についてはServerの設定によるらしいが
そこまでやっていないので私も?
ただし同一コマンドの場合一度翻訳されたものが保持されているので
次回は翻訳されづ実行されます、このため2回目以降の動作は多少速く
なるようになっています
ただしこれは、発行元アプリケーションが起動されている間だけ有効で一度
アプリケーションが終了するとアプリケーションで発行したコマンドは破棄
されてしまいます
MFCクラスを利用することは、コンパイル済みコマンドを発行するのと
同じ効果を得られるという解説を見たことあるよ
woodさん
ご返答ありがとうございます。
以前までは
OpenExを利用していたのですが
ご指摘の通りに
Openを利用し、
下記の通り
pDoc->m_database.Open=(TEST_ISP,FALSE,FALSE,ODBC;UID=test;PWD=test,FALSE);
に変更してみました。(最後の引数をTRUEにするとダイナセットが使用できないという
エラーがでたのでFALSEにしました、MSDNの仕様でもそのようでしたので)
しかしながらEditを指定した時点で
読み込み専用となってしまいます。
また
CDatabase.ExecuteSQL
を利用時についてですが、毎回SQLコマンドの内容を変えております。
woodさんの例でいきますと
>>CCOSSet mCOS_Set(&pDoc->m_database);
上記での検索レコード数が7万件で、
>>CTANSet mTAN_Set(&pDoc->m_database);
で1レコードに絞るといったものですが、
その際において
CCOSSet,CTANSetはクラスが違うもののレコードは同じでクラスウィザード
で作成したものです。
また、なにかご指摘等がございましたら、お手数ですが
ご返答戴ければ幸いです。
woodさん失礼いたしました。
どうやら、作業をしているテーブルの問題のようでした。
更新は無事できました。
お付き合いして頂きお手数をおかけいたしました。
その他のテーブルでは、複数→単レコードで
の更新が可能でした。