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

[DocWiki 번역] SQL 스크립트 질문과 답변 (FireDAC)


Recommended Posts

Docwiki에 있는 "SQL Scripts Questions (FireDAC)"을 번역한 글: 번역일: 2022년 4월 18일

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

 

SQL 스크립트 실행 관련 질문과 답변을 정리한 목록이다.

 

Q1: 쿼리 끝에서 세미콜론(;)을 사용하지 못하는 이유는? 쿼리에서 이것을 제거했더니 작동한다.

A: ';'는 많은 SQL 스크립트 사투리에서 SQL 명령(command)의 구분자(delimiter)일 뿐이고, SQL 언어가 아니다. 몇몇 DBMS에서는 SQL 명령(command)의 끝에 ';'을 허용하고, 어떤 것들은 허용하지 않는다. 다시 말하자면, 그냥 ';'를 제거하라. 

 

Q2: 몇몇 DBMS (PG, Oracle, FB)에서는 SQL 구문을 오직 하나만 실행할 수 있다. 하지만, SQLite 에서는 구문 여러 개를 한번에 실행할 수 있다. 왜 그런가?

A: 그렇게 설계되어 있기 때문이다 – ExecSQL 메소드는 SQL 명령을 있는 그대로 DBMS API에게 전달한다. 만약 DBMS에서 "묶음(batch)" 쿼리를 지원한다면, 실행이 될 것이고, 그렇지 않다면 실패할 것이다. TFDScript를 사용하면 SQL 명령(command) 여러 개를 담은 SQL 스크립트들을 실행하고 명령을 제어할 수 있다.

 

Q3: 스크립트가 1개 이상 있는데도, ExecuteAll는 오직 첫번째 스크립트만 실행한다.

A: 첫번째 스크립트가 "근본(root)" 스크립트이다. 다른 스크립트들 실행하려면, "근본(root)" 스크립트에서 명시적으로 호출해야 한다. 예를 들면:

with FDScript1.SQLScripts do begin
  with Add do begin
    Name := 'root';
    SQL.Add('@first');  // 명시적으로 '첫번째' 스크립트 호출
    SQL.Add('@second'); // 명시적으로 '두번째' 스크립트 호출
  end;
  with Add do begin
    Name := 'first';
    SQL.Add('create table t1 ...;');
    SQL.Add('create table t2 ...;');
  end;
  with Add do begin
    Name := 'second';
    SQL.Add('create procedure p1 ...;');
    SQL.Add('create procedure p2 ...;');
  end;
end;

ExecuteStepTFDScript.Position 지점으로 부터 그 다음 스크립트 명령을 실행한다. ExecuteAll은 스크립트 전체를 실행한다. ValidateAll / ValidateStep 메소드도 있다. 이 메소드들은 스크립트를 진행하지만, SQL 스크립트를 실행하지는 않는다. ValidateAll을 호출하면 TFDScript.TotalJobSize에 값을 할당(assign)한다. 따라서 그 다음에 ExecuteAll을 호출하면 TFDScript.TotalPct10Done을 올바르게 업데이트 한다. 이것은 진행된 스크립트 명령의 10%에 해당된다.

 

 

Q4: (1) 각 SQL 구문마다 FDConnection.ExecSQL 실행하기 (2) FDScript.ExecuteAll 실행하기는 성능 상 차이가 있는가? :

A: 이 2개의 메소드 뒤에서 SQL을 실행하는 코드는 동일하다. 둘 다 IFDPhysCommand.Execute 메소드를 사용한다. 

TFDScript 파서(parser, 구문 분석기)는 고도로 최적화되어 있다. 이 파서는 Oracle PL/SQL (여기에서는 명령문 안에 ';'이 들어 있을 수 있다) 등 DBMS 마다 제각각인 많은 SQL 사투리를 인식하며 정밀하고 유연하게 제어한다.

 

따라서, 당신이 FDConnection.ExecSQL에 한번에 하나의 명령(command)을 제출한다면, 이런 명령들을 별도의 스크립트 하나로 뽑아 내거나 할 필요가 없다. FireDAC이 알아서 가장 빠른 방식을 사용할 것이다. 만약 SQL 스크립트가 파일 하나 안에 들어 있다면 FDScript.ExecuteAll이 가장 빠른 방식이다.

 

 

Q5: 스크립드 작업이 실패했을 때 롤백(ollback)하는 방법은?

A: 1) Use FireDAC 트랜젝션 제어를 사용한다: 

FDConnection1.StartTransaction;
try
  FDScript1.ExecuteAll;
  FDConnection1.Commit;
except
  FDConnection1.Rollback;
  raise;
end;

2) Oracle인 경우 PL/SQL 블록을 사용하고, 다른 DBMS라면 이와 유사한 구조를 사용한다:

begin
  insert into u_btk.t_test values (1, sysdate);
  insert into u_btk.t_test values (2, sysdate);
  insert into u_btk.t_test values (1, sysdate);
  commit;
exception
  when others then
    rollback;
    raise;
end;

3) TFDScript.OnError를 사용한다: 

procedure TForm1.FDScript1Error(ASender: TObject;
  const AInitiator: IFDStanObject; var AException: Exception);
begin
  FDConnection1.Rollback;
end;

 

Q6: 아래 스크립트를 FB(파이어버드)에서 실행하면, “Unexpected end of command line 3” 에러가 난다. 어떻게 고치나?

EXECUTE BLOCK 
AS 
DECLARE VARIABLE MYVAR VARCHAR(250); 
BEGIN 
... 
END;

A: block(블록)을 가진 SQL 스트립트를 실행하려면, block(블록) 앞에서 명령 구분자(command separator)를 변경해야 한다. 원한다면 블록 처리 뒤부터 다시 원래대로 돌려놓을 수도 있다. 예를 들면; 

SET TERM #; 
EXECUTE BLOCK 
...
END; 

#

SET TERM ;#

 

이 댓글 링크
다른 사이트에 공유하기

  • Kori changed the title to [DocWiki 번역] SQL 스크립트 질문과 답변 (FireDAC)

이 토의에 참여하세요

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

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...

중요한 정보

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