Q&A

  • Zeos + DBGrid + DBNavigator 문제 외
델파이 입문자입니다.
처음으로 해보는 프로젝트에서 몇군데가 막혀서 일주일째 머리 싸매고 있습니다.
ZeOS 6.1.2 beta를 사용해 MySQL에 접속하는 간단한 DB 프로그램입니다.
그리 복잡한게 아니라서 그냥 DB Grid, DB Text로 왠만한 건 다 처리할 수 있으리라 생각했는데, 잘 안되는군요.
--------------

기본적으로 TZQuery는 CachedUpdate=True, RequestAlive=True 상태이고
TZUpdateSQL을 함께 사용하고 있습니다.
DB Grid는 TMS의 DBAdvStringGrid를 사용하고 있습니다.

[1] 조인된 테이블의 업데이트 문제

SELECT A.*, B.* FROM A LEFT JOIN B ON A.id=B.no ORDER BY A.id 와 같은 식으로
테이블 A, B 를 JOIN해서 읽어온 결과를 DB Grid에 뿌려줍니다.
DB Grid에서 선택한 열의 상세정보를 옆쪽 DB Text에 뿌려줍니다.
이렇게 조회에는 별 문제가 없습니다.

문제는 업데이트인데요.
오른쪽 DB Text에서 몇몇 값을 변경하고 "업데이트"를 시키면
A 테이블의 값은 변경이 되는데, B 테이블의 값은 변경이 안됩니다.

할 수 없이 별도의 TZQuery를 하나 더 마련하여
여기에 직접 SQL문(update)을 입력해서 ExecSQL을 실행하는데,
그래도 업데이트가 안되는군요. 도대체 이유를 모르겠습니다.
B 테이블을 업데이트하는 코드는 다음과 같습니다.

     DM1.ZQ_t.SQL.Clear;
     DM1.ZQ_t.SQL.Add('UPDATE addrbook SET ');
     DM1.ZQ_t.SQL.Add(' dong=:DONG, bunji=:BUNJI, tongban=:TONGBAN, ');
     DM1.ZQ_t.SQL.Add(' addr2=:ADDR2, zip=:ZIP, tel=:TEL ');
     DM1.ZQ_t.SQL.Add(' WHERE id=:SEDAE ');
     DM1.ZQ_t.ParamByName('SEDAE').AsInteger := sedae_ID;
     DM1.ZQ_t.ParamByName('DONG').AsString := DBEdit33.Text;
     DM1.ZQ_t.ParamByName('BUNJI').AsString := DBEdit34.Text;
     DM1.ZQ_t.ParamByName('TONGBAN').AsString := DBEdit35.Text;
     DM1.ZQ_t.ParamByName('ADDR2').AsString := DBEdit36.Text;
     DM1.ZQ_t.ParamByName('ZIP').AsString := DBEdit14.Text;
     DM1.ZQ_t.ParamByName('TEL').AsString := DBEdit9.Text;
     DM1.ZQ_t.ExecSQL;

[2] DB Grid + DB Navigator 로 데이터를 추가, 수정하는 문제

하나의 테이블을 읽어와서 DB Grid에 뿌려줍니다.
DB Grid에서 열을 선택하면, 아래쪽 DB Text에 그 값을 출력합니다.
(위와 같은 형태입니다.)
여기서도 문제는 INSERT, UPDATE 입니다.

DBAdvNavagator의 버튼을 이용해, 데이터를 삽입, 업데이트하려고 하는데요.
(+)버튼을 눌러 insert를 하면 DB Grid에 열이 하나 삽입되지요.
이때, 수동으로 입력하지 않은 값이 있습니다.
무슨 말인가 하면, 테이블에는 a,b,c,d 필드가 있는데
사용자가 입력하는 값은 b, c,d 이고
프로그램 상에서 a 값을 지정한다는 말입니다.
저는 FieldByName('')을 이용해 값을 지정해주었습니다.
그런데 ApplyUpdate, CommitUpdate를 하지 않고
계속 (+)버튼을 눌러 여러개의 데이터를 insert하도록 시도하면
위와 같이 값을 지정할 수 없고, 결국 insert가 실패합니다.
궁여지책으로 만든 코드는 다음과 같습니다.

DM1.ZQ_sv.Insert;
DM1.ZQ_sv.ParamByName('ID').AsInteger := curr_ID;
DM1.ZQ_sv.FieldByName('ID').AsInteger := curr_ID;
DM1.ZQ_sv.FieldByName('FAVOR').AsInteger := 0;
DM1.ZQ_sv.Post;
DM1.ZQ_sv.ApplyUpdates;
DM1.ZQ_sv.CommitUpdates;
DM1.ZQ_sv.First;

(+)버튼을 누를때나 (v)버튼을 누를때마다 곧장 Commit해버리는거지요.
그런데 이렇게 해도 깔끔하게 동작하지 않고
때때로는 update가 작동하지 않기도 합니다.

--------------
그냥 DBGrid + DBText로 뚝딱뚝딱 프로그램이 만들어질 줄 알았는데, 참 쉽지 않네요.
아는 형의 부탁으로 간단한 아르바이트로 맡은 일이라
누구한테 맡겨서라도 빨리 해결하고 싶은데, 시간이 촉박하네요.
T.T
2  COMMENTS
  • Profile
    김경록 2004.01.01 02:32
    아직 연결 및 DB Action에 대한 개념이 안잡혀지신것 같군여
    저는 일단, Zeos 6.1.2 beta는 써보지 않았지만,
    그 이전 버젼을 써서 Project를 수행했던 적이 있었습니다.
    물론, 에러없고, Insert/update/delete 잘 수행했습니다..

    일단, 님의 문제는
    1.  CachedUpdate=True, RequestAlive=True
        ==>  이건 2개 이상의 table에서 select 해서 가져온 data에 대해서
               RequestAlive는 허락되지 않습니다.
               따라서, Insert/update/delete를 수행할 수 없습니다..
               무조건, Error 이거나, 모든 Action은 실패합니다.

               조치법:     RequistAlive=False

    2.  UpdateSql 1개를 가지고, 2개의 Table에 Insert/Update/Delete를
        수행할 수 없습니다..
         왜야하면, UpdateSQL 컴포넌트의 Insert/Modified/Delete SQL속성은
         1개의 SQL문이 들어갈 수 있기 때문에
         여러개의 Table에 대해서 수행하고 싶다면,
         당연히, Query 컴포넌트에서 지정된 UpdateSQL을 바꿔 가면서
         수행을 해야 합니다.
         아니면, Query 컴포넌트의 AfterPost 이벤트에서
         다른 Query로 직접 다른 table에도 insert/update/delete하는
         문장을 넣어줘야 합니다.

    3.  여러번의 Action(Insert/Update/Delete) 후
        post를 하는 방식은 제가 수행해 보지 않아서 잘 모르겠구여..
        저같은 경우에는
        특정 Row를 변경했다면, 다른 Row로 focus가 이동하거나
        저장버튼을 누를때에 post를 시키는 방식을 취했습니다.
        즉, 1 Row 별로 Post를 수행했다는 뜻입니다.
        (물론, 이것이 CachedUpdate에 대해서 이론상 좋지 못한
         수행 결과를 낳을지 모르더라도 저는 이렇게 사용했다는 뜻입니다.)

    답이 되셨는지 모르겠군여
    예제가 필요하시다면, 자료실에 제가 올려놓은
    예제를 추천해 드리고 싶군여.. (갠적으로 1000건이 넘었군여..  *^^*)








  • Profile
    초보자 2004.01.03 16:15
    답변 감사합니다.


    네, 바로 그게 문제입니다.


    RequestAlive=True 일때에도 일부 쿼리는 성공하던걸요. 완전하지 않은 문장인데오 알아서 실행하는 것처럼 보입니다. 그래서 더 헷갈리는 것 같습니다.
    RequestAlive=False 로 했더니 그밖의 여러 기능에 제한이 있어서요. 그냥 True로 쓰기로 했습니다.


    Zeos6.1.2에는 Multi SQL 이 들어가는 것 같던데요. 성공하지는 못했습니다.
    아무튼 말씀하신 것처럼 ZQuery 하나에 UpdateSQL을 2개 만들어서 해결했습니다.

    문제는 어떻게 해결했지만, 아직도 이해가 되지 않는 것은...
    데이터셋과 별도로 임시쿼리를 만들어 ExecSQL을 실행해도 이게 제대로 작동하지 않는다는 겁니다.
    또 ZQuery가 과연 ZUpdateSQL을 제대로 사용하는지도 의심스럽습니다.
    의외로 문서찾기도 쉽지 않구요.