///////////////////////////////////////////////////////////////////////////
우선 답변에 감사드립니다. 요청하신데로 소스를 통째로 올려 드립니다..
답변 부탁 드립니다..
///////////////////////////////////////////////////////////////////////////
아래의 요지는 키값이 순차적으로 들어 가있는 필드에서 만 약레코드가 10000개쯤된다고 하면 .. 그중에서 중간에 삭제된 부분을 찾아내서 그 키값으로 새로운 레코드를 삽입 할려고 하거든요..
void __fastcall TForm8::Button1Click(TObject *Sender)
{
AnsiString ADate;
int i;
TQuery *TemQry;
TemQry = new TQuery(this);
TemQry->DatabaseName = "geredb";
TemQry->Close();
ADate = FormatDateTime("yyyy-mm-dd",Form6->DateTimePicker1->DateTime);
TemQry->SQL->Clear();
//SQL 문 작성부분
TemQry->SQL->Add( "select cast((cast(c_snno as integer) +1) as char(5)) "
"from gerecher.db where c_date like :PDate"
" and not(cast(c_snno as integer) = :count)");
// TemQry->Prepare();
for (i=1; i < 4220; i=i+1)
{
this->Caption = IntToStr(i);
TemQry->ParamByName("PDate")->AsString = ADate;
TemQry->ParamByName("count")->AsInteger = i;
TemQry->Open();
// 여기서 아래 넥스트 문이 없으면 db상에서 커서가 이동을 하지 않더군요..
// next문도 속도가 느리더라구요 ..
// 검색하는데 20분씩걸리면 사용자가 짜증나서 못쓰겠지요..
// 어떻게 방법이 없을까요? .. 이부분 꼭좀 알려 주세요..
TemQry->Next();
//레코드가 없으면 그부분에 1개 삽입한다..
Button2->Caption = TemQry->Fields->Fields[0]->AsString;
if ( TemQry->RecordCount == 1 )
{
TemQry->Close();
DataModule5->Query1->DisableConstraints();
DataModule5->Query1->Close();
DataModule5->Query1->SQL->Clear();
DataModule5->Query1->SQL->Add("Insert Into gerecher.db (C_date, c_snno) "
"values ('"+
FormatDateTime("yyyy-mm-dd",
Form6->DateTimePicker1->DateTime)+"', '"+Format("%05d", ARRAYOFCONST(((int)StrToInt(i))))+"')");
DataModule5->Query1->ExecSQL();
DataModule5->Query1->Close();
DataModule5->Query1->SQL->Clear();
DataModule5->Query1->SQL->Add("Select * From gerecher.db "
"Where c_date = '"+
FormatDateTime("yyyy-mm-dd",
Form6->DateTimePicker1->DateTime)+"'");
DataModule5->Query1->Open();
DataModule5->Query1->Last();
AnsiString As_date;
As_date = Format("%05d", ARRAYOFCONST(((int)StrToInt(i))));
////////////
// 비어있는 키값을 찾아서 그곳으로 커서를 이동시켜주는 부분.
// 그리드 상의 커서 이동..
///////////////////////////////////////////////////////////////////////////////
TLocateOptions Opts;
Opts.Clear();
Opts << loCaseInsensitive;
Variant locvalues[2];
locvalues[0] = Variant(FormatDateTime("yyyy-mm-dd",Form6->DateTimePicker1->DateTime));
locvalues[1] = Variant(Format("%05d", ARRAYOFCONST(((int)StrToInt(i)))));
DataModule5->Query1->Locate("C_date;C_snno", VarArrayOf(locvalues, 1), Opts);
///////////////////////////////////////////////////////////////////////////////////////////
DataModule5->Query1->EnableConstraints();
break; // for 구문 밖으로 탈출..
}
else
{
TemQry->Close();
}
// Form8->Hide();
} // for(;;;) 문의 끝..
TemQry->Close();
delete TemQry;
}
오현수 입니다.
올려주신 소스의 내용을 보니
Paradox : gerecher.db 데이블의
c_date char(10),
c_snno char(5)
두 필드를 조합키로 사용하시는 것 같군요.
SQL문을 보니 두 조합키로 작성된 레코드가 비어 있을 때, 그 자리에 새로운 레코드를
넣으시려는 것 같고요.
다시 말씀드리면 Query의 질의 반복에 따른 속도저하가 가장 큰 문제 인것 같군요,
해결 방안은 몇가지가 일을 것 같은데요,
날짜 필드인 'c_date'의 중복 정도가 궁굼하긴 하지만, 만일 특정 날짜에 대한 레코드수가
그리 많지 않다면 아래와 같은 방법을 사용하시는 것이 속도 면에서 빠를 것 입니다.
특정 날짜의 레코드만을 검색한 후
Next()로 다음 레코드로 이동하면서 비어있는 c_snno을 찾는 것입니다.
SQL문장은 _______________________________
SELECT CAST(s_snno AS INTEGER) AS sn
FROM gerecher
WHERE c_date = :Pdate
ORDER BY s_snno
_________________________________________
날짜필드를 DATE가 아닌 char(10)의 문자형으로 사용하시니 사용하신 것과 같이
Pdate는 문자열로 변화 후 대입을 하여야 하고요,
올려주신 소스를 보니 비어있는 조합키중에서 c_snno의 값이 가장 작은 것 하나에만
레코드를 추가(append)를 해주면 되는 것 같은데요, 그렇다면 위의 SQL문에서 와 같이
ORDER BY로 정렬울 수행하고
int ret;
...
TemQry->Open();
for(int i=1,ret; 1 ; i++){
ret = TemQry->FieldByName("sn")->AsInteger;
if( ret == ret) TemQry->Next();
else{
ret = i; //비어있는 s_snno의 값이 됩니다.
break;
}
};//end of for
TemQry->Close();
위와 같이 작성하면 비어있는 s_snno값을 쉽게(또한 빠르게)찾으실 수 있을 것입니다.
ret값이 비어 있는 s_snno값이니까 아래에서 처리를 하시면 되겠죠!
참 위의 for loop안에서 TemQry->Eof()의 상태를 확인하는 코드를 넣으셔야 합니다.
제가 지금 Delphi로 작업중이라 C++Builder에서 코딩을 해보지 못해서
코드에 약간의 문제가 있을지도 모르겠습니다.
레코드수가 변수이긴 하지만 Paradox의 경우 Next()가 비교적 빠른 편이어서
속도가 상당히 향상 되리라고 생각합니다.
문제가 해결되지 않는다면
다시 올려주시기 바랍니다.
수고하세요 .. :)
다급한놈... wrote:
> ///////////////////////////////////////////////////////////////////////////
> 우선 답변에 감사드립니다. 요청하신데로 소스를 통째로 올려 드립니다..
> 답변 부탁 드립니다..
> ///////////////////////////////////////////////////////////////////////////
>
> 아래의 요지는 키값이 순차적으로 들어 가있는 필드에서 만 약레코드가 10000개쯤된다고 하면 .. 그중에서 중간에 삭제된 부분을 찾아내서 그 키값으로 새로운 레코드를 삽입 할려고 하거든요..
>
>
>
>
> void __fastcall TForm8::Button1Click(TObject *Sender)
> {
> AnsiString ADate;
> int i;
>
> TQuery *TemQry;
> TemQry = new TQuery(this);
> TemQry->DatabaseName = "geredb";
> TemQry->Close();
> ADate = FormatDateTime("yyyy-mm-dd",Form6->DateTimePicker1->DateTime);
> TemQry->SQL->Clear();
>
> //SQL 문 작성부분
>
> TemQry->SQL->Add( "select cast((cast(c_snno as integer) +1) as char(5)) "
> "from gerecher.db where c_date like :PDate"
> " and not(cast(c_snno as integer) = :count)");
> // TemQry->Prepare();
> for (i=1; i < 4220; i=i+1)
> {
> this->Caption = IntToStr(i);
> TemQry->ParamByName("PDate")->AsString = ADate;
> TemQry->ParamByName("count")->AsInteger = i;
> TemQry->Open();
>
> // 여기서 아래 넥스트 문이 없으면 db상에서 커서가 이동을 하지 않더군요..
> // next문도 속도가 느리더라구요 ..
> // 검색하는데 20분씩걸리면 사용자가 짜증나서 못쓰겠지요..
> // 어떻게 방법이 없을까요? .. 이부분 꼭좀 알려 주세요..
>
> TemQry->Next();
> //레코드가 없으면 그부분에 1개 삽입한다..
> Button2->Caption = TemQry->Fields->Fields[0]->AsString;
> if ( TemQry->RecordCount == 1 )
> {
> TemQry->Close();
> DataModule5->Query1->DisableConstraints();
> DataModule5->Query1->Close();
> DataModule5->Query1->SQL->Clear();
> DataModule5->Query1->SQL->Add("Insert Into gerecher.db (C_date, c_snno) "
> "values ('"+
> FormatDateTime("yyyy-mm-dd",
> Form6->DateTimePicker1->DateTime)+"', '"+Format("%05d", ARRAYOFCONST(((int)StrToInt(i))))+"')");
>
> DataModule5->Query1->ExecSQL();
> DataModule5->Query1->Close();
> DataModule5->Query1->SQL->Clear();
> DataModule5->Query1->SQL->Add("Select * From gerecher.db "
> "Where c_date = '"+
> FormatDateTime("yyyy-mm-dd",
> Form6->DateTimePicker1->DateTime)+"'");
> DataModule5->Query1->Open();
> DataModule5->Query1->Last();
> AnsiString As_date;
> As_date = Format("%05d", ARRAYOFCONST(((int)StrToInt(i))));
>
> ////////////
> // 비어있는 키값을 찾아서 그곳으로 커서를 이동시켜주는 부분.
> // 그리드 상의 커서 이동..
> ///////////////////////////////////////////////////////////////////////////////
>
> TLocateOptions Opts;
> Opts.Clear();
> Opts << loCaseInsensitive;
> Variant locvalues[2];
> locvalues[0] = Variant(FormatDateTime("yyyy-mm-dd",Form6->DateTimePicker1->DateTime));
> locvalues[1] = Variant(Format("%05d", ARRAYOFCONST(((int)StrToInt(i)))));
> DataModule5->Query1->Locate("C_date;C_snno", VarArrayOf(locvalues, 1), Opts);
>
> ///////////////////////////////////////////////////////////////////////////////////////////
> DataModule5->Query1->EnableConstraints();
> break; // for 구문 밖으로 탈출..
>
> }
> else
> {
> TemQry->Close();
> }
> // Form8->Hide();
> } // for(;;;) 문의 끝..
> TemQry->Close();
> delete TemQry;
>
> }