Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

[DocWiki 번역] TFDQuery, TFDStoredProc, TFDUpdateSQL 질문과 답변


Recommended Posts

Docwiki에 있는 "TFDQuery, TFDStoredProc and TFDUpdateSQL Questions (FireDAC)"을 번역한 글: 번역일: 2022년 4월 18일

위로 가기: [DocWiki 번역] FAQ (FireDAC)

 

TFDQuery, TFDStoredProc, TFDUpdateSQL 관련 질문과 답변을 정리한 목록이다.

 

Q: TFDQuery를 사용하여, 데이터셋 프로바이더에 연결하고 엠바카데로 클라이언트 데이터셋 안에 있는 데이터를 꺼내올 수 있나?

A: TFDQuery에는 TFDMemTable과 TFDTableAdapterTFDCommand 몇 가지가 혼합되어 있다. 따라서 TFDQuery 안에는 SQL 명령(command) 실행, 파라미터 데이터 전달, 결과 세트(result set)를 받아서 저장, 결과 세트 안을 이동, 데이터 변경을 데이터베이스로 다시 전송(post) 등을 수행할 때 필요한 모든 것이 들어있다. TFDQuery + DSP(데이터셋 프로바이터) + CDS(클라이언트 데이터셋)을 함께 사용할 이유가 없다.

TFDQuery를 쓰지 않고 대신에 TFDMemTable, TFDTableAdapter, TFDCommand 각각을 직접 따로 사용할 수도 있다. 그러면 더 유연하겠지만, 코딩은 더 많이 해야한다. 예를 들어 데이터셋들 전반에 걸쳐있는 동기화되는 캐시된 업데이트 상황를 생각해보라.

다시 말해, TFDQuery는 데이터 애플리케이션 프로그래밍을 매일 하는 개발자를 위해 최적화된 일종의 "지름길"이다.

 

Q: 수작업으로 명시한 파라미터를 FDStoredProc에서 강제로 사용하도록 하려면 어떻게 하면 되나? 

A: FetchOptions.Items 프로퍼티에서 fiMeta를 빼라. 

파라미터를 수작업으로 생성하려면, FetchOptions.Items 프로퍼티에 fiMeta가 없도록 빼는 것이 옳다. 이 옵션이 들어있으면,  FireDA은 저장 프로시저(stored procedure)의 파라미터 정의를 데이터베이스에서 가져와서 Params 컬렉션 안에 넣을 것이다.

파라미터를 수작업으로 정의하기가 어렵다면, Params 컬렉션을 자동으로 채우면(populate) 파라미터들이 어떻게 정의되는 지를 볼 수 있다. 그리고 나서, 당신의 코드와 비교해보라. 

 

Q: '[FireDAC][Phys]-308. Cannot open / define command, which does not return result sets'와  '[FireDAC][Phys]-310. Cannot execute command returning results set' 예외는 어떤 의미인가? 

A: '[FireDAC][Phys]-308. Cannot open / define command, which does not return result sets' 예외는 결과 세트를 반환하지 "않는" SQL 명령(command)의 Open 메소드를 실행할 때 발생한다. 이 예외(exception)가 발생되는 시점은 해당 SQL 명령이 실행했는데 DBMS에서 결과 세트(result set)를 전혀 반환하지 않을 때이다.

'[FireDAC][Phys]-310. Cannot execute command returning results set' exception 예외는 결과 세트를 "반환하는" SQL 명령(command)의 ExecSQL 메소드를 실행할 때 발생한다. 명령(command)이 결과 세트를 반환하는 지 아닌 지는 FireDAC의 SQL 명령(command) 전처리기에 의해서 결정된다. 만약 명령이 SELECT 또는 이와 같은 형식으로 인식된다면 결과 세트를 반환한다; 그렇지 않으면 반환하지 않는다.

이 예외(exception)가 발생되는 시점은 해당 SQL 명령이 실행했는데 DBMS에서 결과 세트(result set)를 전혀 반환하지 않을 때이다.

경우에 따라 FireDAC가 SQL 명령의 결과 집합 반환 여부 인식하지 못할 수 있다. 그리고 때때로 애드 혹(ad hoc) 애플리케이션은 반환하는 결과 집합의 수에 의존하지 않고 SQL 명령을 실행해야 한다. 그렇다면 이러한 경우에는 어떻게 해야 할까? 두 가지 기본 해결책이 있다.

1)

FDQuery1.OpenOrExecute;

이 방식은 [FireDAC][Phys]-308 예외가 발생될 수 있지만, 그 예외가 OpenOrExecute 밖으로 전파되지는 않는다. 그리고 SQL 명령(command)은 잘 실행된다. 또한, 해당 명령이 결과 세트(result set)를 반환한다면 이 메소드는 True를 반환하여 알려준다. 

2)

FDQuery1.Command.CommandKind := skInsert;
FDQuery1.ExecSQL;

FireDAC에게 (INSERT 등등) 결과 세트를 반환하지 않는 명령(command) 유형을 지정하기만 하면 된다.

 

QFDQuery.Execute(FDQuery.Params.ArraySize)를 호출하면 'Out of memory' 예외가 발생한다. ArraySize는 90,000이다. 뭐가 잘못되었나?

A: 1) 90,000은 어떤 DBMS에도 너무 과도하다. 그 이유는 데이터가 몇번에 걸쳐 캐시(cache)되어야 하기 때문이다 (파라미터, DBMS API 버퍼, 네트워크 패킷 버퍼, 등등). 또한, 아마도 레코드 하나하나의 크기도 상당할 것이다. 또한 애플리케이션은 아마 DBMS API 한도 (예: 허용하는 최대 Array 크기, Oracle에서는 $7FFF까지만 허용하고, 다른 DBMS에서는 네트워크 패킷 크기 등에 따라 다르다)에 당면하게 될 수도 있다.

2) 90,000을 쪼개서 각 덩어리 당 500-5000 항목을 담도록 하라. AD03-ArrayDML 데모를 참고하라. 대개, 덩어리 크기 한도까지 array를 채우고 나서 Execute를 실행할 때 그 덩어리 크기(chunk size)를 전달한다. 그리고 나서 다시 채우기와 Execute를 반복한다.

Firebird 데이터베이스에서, 나는 ArraySize = 1,000,000 (60 초)를 사용했었는데 문제가 없었다. 실험을 통해 얻어진 공식이 있어서 array 하나의 최대 크기를 결정할 수 있다. FireDAC은 자동으로 큰 array 하나를 작은 덩어리도 쪼갠다.

이와 유사한 값을 Oracle에서 찾기는 간단하지 않다. Oracle이 최대 $7FFF까지 지원하지만, 대용량 array에서는 여전히 AV 또는 기타 이슈에 부딪힐 수 있다.

어쨌든, 레코드 하나의 크기가 과도하게 크면, Execute를 호출하기도 전에 메모리가 소진될 수 있다.

 

QFDQuery가 레코드를 "모두" 가져왔는 지를 어떻게 알 수 있나?

A: SourceEOF 프로퍼티를 확인하라. 

 

Q나는 (단순 SQL 문을 통해) 레코드 하나를 삽입(insert)하고 새로 추가된 레코드의 IDENTITY / SEQUENCE 를 받고 싶다. 가장 효율적이고 여러 데이터베이스에서도 사용할 수 있는 방법은 무엇인가

A: 1) TFDConnection에는 GetLastAutoGenValue 메소드가 있다. DBMS에 따라 다르지만, 이 메소드는 가장 세션 하나 안에서 마지막에 자동-생성된 값을 반환한다. 예를 들면 Oracle에서는: 

SELECT <AName>.CURRVAL FROM dual

MySQL에서는, SQL 쿼리를 사용하지 않고 MYSQL API를 접근하여 값을 받아온다. 또한, DBMS에서 sequences/generator를 지원하지 않는다면, AName 파라미터 값은 그저 무시된다.

2) 레코드를 IMSERT하고 자동-생성된 값을 받아오는 SQL 명령문을 작성하는 공통된 일반적인 방식은 없다. 예를 들면 Oracle에서는:

INSERT ... INTO ... RETURNING ID INTO :ID

PostgreSQL에서는, 명령(command) 두개를 나누어 실행한다: 

INSERT ... INTO .. 
SELECT CURRVAL(...)

당신이 TDataSet Insert/Post 메소드를 사용하여 데이터베이스에 INSERT를 하나 전송(post)하면, FireDAC은 DBMS kind를 보고 효율적이고 적절한 SQL 명령(command)을 생성한다.

 

Q사용자가 amCancelDialog 모드에서 쿼리 실행을 취소한 후에 해당 트랜젝션을 롤백(rollback)하는 방법은?

A: 2가지 선택이 있다:

1)

FDTransaction1.StartTransaction;
try
  FDQuery1.ExecSQL;
  FDTransaction1.Commit;
except
  on E: EAbort do
    // 사용자가 해당 명령(command) 실행을 취소했다
    ADTransaction1.Rollback;
end;

2) TFDQuery.OnError 이벤트 핸들러를 생성하라. 명령 실행이 취소되면, 이 이벤트 핸들러가 호출되는데 이때 AException 파라미터를 이용하여 조건을 확인하여 맞춤 처리를 할 수 있다:

EFDDBEngineException(AException).Kind = ekCmdAborted;

 

Q내 쿼리 문장에 '&', '!' 문자가 있어서 올바로 실행되지 못한다. 뭐가 잘못되었나?

A: 예를 들면, 다음과 같은 쿼리는 기본 옵션인 경우 실패하게 된다:

FDQuery1.SQL.Text := 'select * from xy where Fieldname = ''xxx&n''';
FDQuery1.open;

DBMS가 받는 SQL 명령에는 '&n'가 빠져있게 된다. 그 이유는 '&'는 매크로 변수의 시작점을 표시하기 때문이다. 기본 설정에서는, 모든 값에는 빈 값이 들어있다. 따라서 '&n'는 빈 문자열(string)로 교체된다. 만약 당신이 매크로를 사용하지 않는다면 ResourceOptions.MacroCreateResourceOptions.MacroExpandFalse로 지정하라.

 

Q: 저장프로시저(stored procedure) 파라미터에 접근할 때 'Parameter Xxx not found' 에러가 났다. 뭐가 잘못되었나?

A: 예를 들면, 코드가 다음과 같다면:

FDStoredProc1.StoredProcName := 'TestProc';
FDStoredProc1.Prepare;
FDStoredProc1.ParamByName('Par').AsInteger := 100;

그 에러는 여러가지 다른 이유들 때문에 발생할 수 있다:

  • 데이터베이스에 "TestProc" 저장프로시저가 없다. 해당 데이터베이스에서 이 저장 프로시저를 만들어야 한다.;
  • DBMS따라 다르지만, "TestProc"가 유효하지 않은 상태일 수 있다. 이 저장프로시저는 반드시 유효한 상태이어야만 한다.;
  • DBMS따라 다르지만, 이 저장프로시저의 이름에 대소문자가 섞여있다. 그대로 인용해야 한다;
  • FetchOptions.Items 프로퍼티에서 fiMeta가 빠져있다; fiMeta가 반드시 들어있거나 또는 수작업으로 파라미터가 생성되어 있어야 한다.;
  • 이 저장프로시저(stored procedure)에 Par라는 파라미터가 없다; 파라미터 이름을 정확하게 맞게 수정하거나 또는 데이터베이스에 Par 파라미터가 추가되어야 한다;
  • DBMS따라 다르지만, 파라미터 이름 앞에 접두사 '@'가 있을 수도 있거나 또는 ResourceOptions.UnifyParamsset를 True로 지정할 수 있다.
이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

 공유하기

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.