안녕하세요! 다음질문은 CachedUpDates 에관한 질문으로
q&a 사이트에 가장많이올라오는 질문중하나가 updatesql 이아닌가 생각해봅니다.
제가 한델의 이 q&a사이트에 올라와 있는것은 전부다 해봐도 무엇이문제인지 알수없어
이렇게 질문하게되었습니다.
1.첫번째질문
Query 컴포넌트를 CachedUpDates 를 true 로 하면
저장버튼에 Query1.ApplyUpDates; , Query1.CommitUpdates; 를 아무리때려도
절대로 저장되지않는데 저장시킬수있는방법이 무엇일까요? (sql 에 order by사용시)
2. 두번째질문
Query 컴포넌트를 RequestLive 를 True로 하지안으면 무조건 Readonly 가되기
때문에 updatesql 을 사용할 이유가 있을까 합니다.
물론 Query 컴포넌트의 CachedUpDates 를 true 로 하고 updatesql 을 같이쓰면
Edit mode 가되긴하지만역시Query1.ApplyUpDates ,Query1.CommitUpdates를 아무리
때리고 AfterPost Event에 다 넣어도 프로그램을종료한후 다시보면 수정데이터가
저장이 안됩니다.
3. 수정저장이되는경우는 CachedUpDates 가 false 일때뿐인데 이경우는 무슨테이블에
인덱스가 없다는메시지가 나오며 에러를 발생시킵니다.
비슷한경험을 하신분이나 잘알고 계신분은 아래항목에 상세한답변 부탁드립니다.
Query 컴포넌트 UpdateSQL 컴포넌트 저장버튼
cachedupdates( ) Query1.ApplyUpDates( )
requestlive ( ) Query1.CommitUpdates( )
updateobject( )
안녕하십니까?
그냥 저의 작은 의견입니다.
그저 참고만이라도
될까 싶어서 이렇게 글을 올립니다.
혹 쓰시는 DB가 무엇입니까?
혹 로컬 DB를 쓰십니까?
다른 로컬 DB는 테스트을 해보질 않았지만,
일전에 패러독스로 테스트 해보았을때
이 DB는 UpdateSQL이 되질 않는다것을 알게되었습니다.
그러나, 서버 DB를 쓰신다면 그런 문제는 없을 듯 합니다.
서버 DB에서는 그리 큰 문제없이 Update는 됩니다.
그런데, 문제는 UpdateSQL는 우선 2가지 문제점이 있습니다.
첫번째, 조인결과에 대해서 참조무결성을 유지하면서
조인에 참가한 여러테이블에대해서 동시에 갱신을 해주질 못한다는
것입니다.
이것은 UpdateSQL를 더블클릭해서 SQL부분을 보면
알 수 있을 것입니다.
참조무결성을 위해 복수쿼리가 존재해야 하는데
항상 단일쿼리로 존재합니다. 문제가 있는 것이죠.
두번째, 가령 select substr(data1, 1, 3).... 이런식의
쿼리에 즉, 필드의 부분값을 가져오는 경우에 있어서는
역시 테이블판단을 제대로 못합니다.
이것이 현 델파이(4.0)에 있는 UpdateSQL의 문제점입니다.
즉, 조인쿼리가 아니라면 UpdateSQL대신 그냥 RequestLive를
쓰시는것이 좋을 듯 합니다.
RequestLive를 쓰신다면 CachedUpdate와 UpdateSQL이 필요없습니다.
이것은 일괄처리는 아닙니다.
그런데, 마치 일괄처리처럼 할 수 있습니다.
그리드에서 데이터를 삽입하든, 수정하든 작업을 마친뒤
사용자는 커서를 위또는 아래로 내리거나 아니면 가만 있을 것입니다.
만약 사용자가 커서를 위 또는 아래로 움직인다면 자동으로 갱신이
이루어 집니다.
즉, 종료되는 시점에서만 state를 판단해서 마지막 한건이
update가 되었는지 안되었는지 판단해서 갱신만 해주면 됩니다.
간단히 if (query1.state = dsEdit) or (query1.state = dsInsert) then
query1.Post ;
요렇게 말입니다.
그럼, 조인쿼리에 대해서는 어떻게 하는가?
이것역시 감쪽같이 해결 할 수 있습니다.
우선 디비그리드를 편집상태로 만들어야 합니다.
그러기 위해서는 일단 UpdateSQL를 쓰시고요, cachedUpdates를 true로
합니다. 물론 이때는 RequestLive는 false로 합니다.
그러면 그리드상에서는 입력 내지 수정상태가 될 것입니다.
물론 던지신 문제처럼 수정내지 입력이 안될 것입니다.
아무리 applyUpdates해도 말입니다.
(물론 서버 DB라면 그냥 됩니다)
참조무결성을 완벽히 유지하면서 조인결과에 대해서도 갱신을
하는 방법은 바로 그리드의 keyDown이벤트에서 구현을 하면 됩니다.
if (key = vk_down) or (key = vk_up) then
begin
if query1.state = dsInsert then
begin
with query2 do
begin
삽입작업...
end ;
...
end
else if query1.state = dsEdit then
begin
마찬가지...
end ;
end ;
위부분 코딩은 문제에따라 프로그래머가 트랜잭션을 걸어서
코딩을 하는 것이죠. 그리고 동시 갱신 작업도 하는 것입니다.
사용자가 그리드에서 현재 입력을 하든 수정을 하든 그 값을
갖고오는 방법은 DbGrid1.Columns[index].Field.asString(타입)
이런 방법으로 가져오면 됩니다.
사용자는 그리드상에 어떤 연산을 가할 것입니다.
프로그래머는 이미 그리드에서 각 칼럼이 어떤 테이블의 필드인지
알고 있기 때문에 현재 사용자가 갱신하는 레코드의 필드값을 가져오는것은
쉽습니다.
그런데, 주키입니다.
사용자가 주키를 수정하게 해서는 안됩니다.
물론 주키를 수정하게 할 수도 있습니다만,
그러면 그리드의 DrawColumnCell이벤트에 코딩이 들어갑니다.
물론 이 작업은 실제적으로 일괄처리는 아닙니다만,
이런 로직을 통해서 사용자는 레코드 한건한건 갱신할때마다
일일이 저장버튼을 누를 필요가 없다는 것입니다.
그냥 갱신을 하면 되는 것입니다.
다만, 프로그래머는 맨 마지막에 폼를 닫는 시점에서 혹 한건이
갱신이 안되었는지만을 판단해서 갱신해주면 됩니다.
위에서처럼...
물론 applyUpdates 이런거 필요없습니다.
프로그래머는 DataBase컴포넌트(갱신확실성을 위해서) 와 ExecSQL명령만을
이용하면 되죠. 물론 코딩은 다소 길어지겠죠.
그러나, 참조무결성이 완전히 이루어질수있고 로컬DB에서 제대로
안되는 UpdateSQL를 좀 자유(?)스럽게 흉내낼 수 있다는 것이죠.
이상 두서없이 말씀드렸습니다.
컴포넌트 믿고서 작성을 했는데 혹 문제를 일으키거나
컴포넌트 소스도 없다면(혹 있다해도 사실상 수정을 하는 작업은
매우 힘든 작업이라고 생각됩니다) 많은 난감이 있습니다.
그렇기에 위의 작업으로 하신다면 프로그래머의 손이
좀 많이 가야 할 것입니다.
건투를 빕니다.