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

Recommended Posts

Docwiki에 있는 "Local SQL (FireDAC)"를 번역한 글 (번역일: 2022년 3월 5일)

위로 가기: [DocWiki 번역] 명령(command)을 가지고 작업하기 (FireDAC)

목차


일반 (General)

The Local SQL feature allows executing SQL commands, where the TDataSet descendants are used instead of the DB tables. The Local SQL is based on the SQLite database and supports most of the SQLite SQL dialect. As table name, it uses the name of a TDataSet (Name property value) or, alternatively, a specified name. Each queryable dataset must be registered with TFDLocalSQL, the Local SQL engine.

Local SQL은, 데이터베이스의 테이블을 대상으로 SQL 명령을 실행하듯이, (하지만, 테이블 대신) 메모리 안에 있는 TDataSet의 자손을 대상으로 SQL 명령을 실행할 수 있도록 한다. Local SQL은 SQLite 데이터베이스를 기반으로 한다. 그리고 SQLite에서 사용되는 SQL구문 대부분을 지원한다. 테이블명으로는 TDataSet의 Name 프로퍼티에 지정한 이름 값을 사용한다. 또는 특정 이름을 명시하고 사용할 수도 있다. 데이터셋을 대상으로 쿼리를 실행하려면, 먼저 해당 데이터셋을 Local SQL 엔진인 TFDLocalSQL에 등록해야 한다.

All the read and write operations are performed through the TDataSet API with some extensions. The engine supports as FireDAC, as non-FireDAC datasets. Local SQL is more effective with FireDAC datasets. Optionally, for non-FireDAC datasets, the IFDPhysLocalQueryAdapter interface can be implemented as an adapter class and registered with the Local SQL engine.

모든 읽기와 쓰기 동작은 TDataSet의 기본API와 확장 API를 통해서 수행된다. Local SQL 엔진은 FireDAC 뿐만 아니라 FireDAC이 아닌 데이터셋도 지원한다. Local SQL은 FireDAC 데이터셋에서 보다 효과적이다. 원하면, FireDAC이 아닌 데이터셋을 사용할 때 IFDPhysLocalQueryAdapter 인터페이스를 어댑터 클래스로 구현하여 Local SQL 엔진에 등록할 수 있다.


The possible applications of Local SQL are:

  • Heterogeneous queries (queryable datasets have result sets from different DBs).
  • In-memory database (TFDMemTables are serving as the datasets).
  • Advanced offline mode. In this case, although the main DB is not accessible, an application is still able to perform the SQL queries.
  • Advanced DataSnap client (the data delivered by the DataSnap driver to the client can be queried locally).
  • Simplified migration. A developer can use the third-party TDataSet objects in an application, and use FireDAC API to work with these data sources.

Local SQL 활용:

  • 이기종 쿼리 (서로 다른 DB에서 쿼리한 결과를 별도의 데이터셋 안에 넣고, 그 데이터셋들을 대상으로 JOIN 쿼리를 할 수 있다)
  • 인-메모리 데이터베이스 (TFDMemTable을 데이터셋으로 사용한다)
  • 고급 오프라인 모드. 이 모드에서는, 주 DB에 접근할 수 없는 경우에도 애플리케이션에서 해당 SQL 쿼리가 동작할 수 있다.
  • 고급 데이터스냅(DataSnap) 클라이언트. 데이터스냅 드라이버가 클라이언트에게 전달한 데이터를 로컬에서 쿼리할 수 있다.
  • 마이그레이션 단순화. 개발자가 애플리케이션에서 써드-파티 TDataSet을 사용할 수 있다. 이 TDataSet 데이터 소스를 FireDAC API를 사용하여 다룰 수 있다.

 

구성하기 (Configuring)

FireDAC uses the SQLite driver as the Local SQL engine. So first, the application should have an SQLite "local" connection. This can be a file-based read-write connection, such as an in-memory connection. We recommend using an in-memory connection. To set it up, execute the following steps:

  • Drop a TFDPhysSQLiteDriverLink component on the form.
  • Drop a TFDConnection.
  • Set its DriverName to SQLite.

FireDAC은 SQLite를 Local SQL 엔진으로 사용한다. 따라서 가장 먼저, 애플리케이션에 SQLite "로컬" 연결이 있어야 한다. (인-메모리 연결 등) 파일 기반 읽기-쓰기 연결을 구성할 수 있다. 인-메모리 연결을 권장한다. 구성하려면 다음 절차를 진행한다. 

The application should connect the datasets to the Local SQL engine. For that, perform the following operations:

  • Drop a TFDLocalSQL component on the form.
  • Set its Connection property to a local SQLite connection object.
  • Verify/assign a value to the dataset Name property. This step is required for datasets created dynamically in the code.
  • For a FireDAC dataset, set the TFDAdaptedDataSet.LocalSQL property to the TFDLocalSQL instance.
  • Or, for FireDAC and non-FireDAC datasets, use the TFDLocalSQL.DataSets collection to register the TDataSet and optional adapter with the Local SQL engine. Also, the DataSets collection allow specifying alternative dataset name.

애플리케이션에서 사용하려는 데이터셋(들)을 Local SQL 엔진에 연결할 차례이다. 다음 절차를 진행한다.

  • TFDLocalSQL 컴포넌트를 폼 위에 올려 놓는다.
  • 올려 놓은 FDLocalSQL의 Connection 프로퍼티에는 앞에서 SQLite드라이버를 연결해 두었던 FDConnection을 지정한다.
  • 올려 놓은 FDLocalSQL의 Name 프로퍼티를 확인/지정 한다. 코드에서 동적으로 생성되는 데이터셋(들)을 연결하려면 FDLocalSQL의 이름을 알아야 하기 때문이다.
  • FireDAC 데이터셋 하나를 사용할 때는, TFDAdaptedDataSet.LocalSQL 프로퍼티에 앞에서 만든 FDLocalSQL 인스턴스를 지정한다.
  • FireDAC 데이터셋(들)과 FireDAC이 아닌 데이터셋(들)을 사용할 때는, 사용할 TDataSet (필요한 경우 어댑터 포함)을 앞에서 만든 FDLocalSQL 인스턴스의 TFDLocalSQL.DataSets 컬렉션 프로퍼티 안에 등록한다. 이 컬렉션에 등록된 데이터셋 각각에는 Name 프로퍼티가 있으므로, 여기에서 해당 데이터셋의 이름을 지정할 수도 있다. 

Finally, activate the following objects:

  • Enable the local SQLite connection.
  • Enable the Local SQL engine by setting TFDLocalSQL.Active to True.
    Note: If the application is using base datasets and local datasets connected to the same SQLite connection, the connection must be enabled explicitly before any dataset on this connection is opened/executed/prepared. Otherwise, an exception is raised.

Alternatively, datasets can be submitted to the Local SQL engine by using the TFDLocalSQL.OnGetDataSet event handler.

마지막으로, 앞에서 생성한 오브젝트(들)을 다음과 같이 활성화한다.

  • Local SQL 엔진에 대한 연결을 담고 있는 FDConnection의 Active 프로퍼티을 True로 지정하여 활성화 한다.
  • Local SQL 엔진인 FDLocalSQL.Active 프로퍼티을 True로 지정하여 활성화 한다.

주의: 애플리케이션에서 로컬 데이터셋과 기반 데이터셋을 동일한 FDConnection에 연결하여 사용한다면, 이 연결을 통해 데이터셋을 오픈/실행/준비하기 전에 반드시 이 FDConnection을 먼저 명시적으로 활성화 해야한다. 그렇지 않으면 예외(exception)가 발생한다. 

대체 방법으로, Local SQL 엔진인 TFDLocalSQL.OnGetDataSet 이벤트 핸들러를 사용하여 데이터셋(들)을 Local SQL 엔진에 넣을 수도 있다.

All associated datasets will be registered with the engine when both local connection and Local SQL engine are active. Associating a new dataset does not require reopening something, and it will be registered automatically. After its registration, a dataset is opened. A TFDMemTable must have a defined structure before it is opened. When the application performs a massive datasets registration, we recommended to deactivate the Local SQL engine before, and activate it after the task.

연결해 놓은 데이터셋(들)은 Local SQL 엔진과 (Local SQL 엔진에 대한 연결을 담고 있는) FDConnection이 모두 활성되는 시점에 Local SQL 엔진에 등록된다.
Local SQL 엔진에 등록된 데이터셋이 이미 있는 상태에는 새 데이터셋을 추가 등록 할 때 다시 오픈하지 않아도 자동으로 등록된다. 등록이 되면 해당 데이터셋이 오픈된다. TFDMemTable인 경우에는 오픈되기 전에 구조가 정의되어 있어야 한다. 애플리케이션에서 엄청 많은 데이터셋(들)을 등록할 때는 Local SQL 엔진을 꺼둔 상태에서 등록하고 등록이 끝난 후에 활성화하기를 권장한다. 

The application can set up TFDLocalSQL.SchemaName to a schema prefix, which will be used in the SQL queries. The application can use multiple TFDLocalSQLs connected to the same connection with or without schema name specified. But each TFDLocalSQL.SchemaName in a SQLite connection must be unique. A schema name allows organizing datasets into logical groups. When a schema name is specified, the dataset in a SQL command can be referenced as <dataset> or <schema>.<dataset>.

애플리케이션 안에 있는 SQL 쿼리에서 스키마 접두사를 사용하기 위해 지정하려면 TFDLocalSQL.SchemaName을 사용한다. 스키마 이름이 명시된 또는 명시되지 않은 TFDLocalSQL들 여러개가 (SQLite를 연결하는) 동일한 FDConnection을 사용해도 되지만, 연결을 공유하는 TFDLocalSQL들 중 SchemaName이 같아서 겹치는 것이 있으면 안된다. 스키마 이름을 사용하면 데이터셋(들)을 논리적인 그룹으로 정돈할 수 있다. SQL Command(명령)에서 스키마 이름이 명시된 데이터셋을 부를 때는 <데이터셋 이름> 또는 <스키마 이름>.<데이터셋 이름>을 사용한다.

Optionally, the application sets TFDLocalSQL.MultipleCursors to False to avoid dataset cloning/copying. SQLite creates a cursor to execute a SQL command referring to a dataset. TDataSet API can keep only a single position. To overcome that, FireDAC clones FireDAC dataset by using TFDMemTable and copies a non-FireDAC dataset to a TFDMemTable. When the programmer is sure that a dataset will be used only a single time in each second, MultipleCursors can be set to False to improve the performance. We do not recommend seting MultipleCursors to False, when there are unidirectional datasets.

선택 사항으로, 애플리케이션에서 TFDLocalSQL.MultipleCursors 프로퍼티를 False로 지정하여 데이터셋이 복제/복사 되는 것을 방지할 수 있다. SQLite는 데이터셋을 부르는 SQL Command(명령)을 실행할 때 커서 1개를 생성한다. 즉, TDataSet API는 데이터셋 안의 한 위치을 기억할 수 있다. 여러 위치를 기억해야 할 경우에, FireDAC은 내부적으로 FireDAC 데이터셋은 복제(clone)를, FireDAC이 아닌 데이터셋은 복사(copy)를 하여 TFDMemTable을 추가로 만든다. 개발자가 판단하기에 데이터셋을 초당 한번만 사용하는 것이 확실하다면, MultipleCursors 프로퍼티를 False로 지정하여 성능을 향상시킬 수 있다. 단방향 데이터셋이 있다면 MultipleCursors 프로퍼티를 False로 지정하는 것을 권장하지 않는다. 

 

쿼리하기 (Querying)

To perform a Local SQL query, the application should use TFDQuery/TFDCommand, and set Connection/ConnectionName to the local SQLite connection, that is also set for the TFDLocalSQL.Connection. Now, the application can execute SQL queries just as with non-Local SQL connections.

Local SQL 쿼리를 수행하려면, 애플리케이션에서 TFDQuery/TFDCommand를 사용한다. 그리고 앞에서 FDLocalSQL.Connection에  지정했던 그 local SQLite Connection을 TFDQuery/TFDCommand의 Connection/ConnectionName 프로퍼티에도 동일하게  지정한다. 

While a query is processing, a queryable dataset is disabled by DisableControls, and enabled when the processing is complete. To keep a dataset enabled, set TFDLocalSQL.DisableControls to False. Before a dataset is read, the TFDLocalSQL.OnOpenDataSet event handler is called.

쿼리가 처리되는 동안, 쿼리 대상이 되는 데이터셋은 DisableControls에 의해 비활성화되며, 처리가 끝난 후에 다시 활성화된다. 데이터셋을 활성화된 상태로 유지하려면 TFDLocalSQL.DisableControlsFalse로 지정한다. 데이터셋 읽기 실행 바로 전에는 TFDLocalSQL.OnOpenDataSet 이벤트 핸들러가 호출된다.

The Local SQL engine supports SQLite SQL dialect with some limitations. The following SQL commands are not supported for the TDataSet data sources:

  • ALTER TABLE ... ADD COLUMN. Instead, change the dataset structure.
  • DROP TABLE. When a dataset is unlinked from the Local SQL engine, it is automatically dropped (not freed).
  • CREATE INDEX / DROP INDEX. Instead of the SQL indexes, use the dataset indexes.
  • CREATE TRIGGER / DROP TRIGGER. Instead of the triggers, use the dataset events.

The Local SQL engine does not support datasets with multiple result sets.

Local SQL 엔진은 SQLite SQL 구문을 지원한다. 하지만 몇가지 제한이 있다. TDataSet 데이터 원본에 대해서 지원하지 않는 SQL 명령은 다음과 같다.

  • ALTER TABLE ... ADD COLUMN: 대신, 데이터셋 구조를 변경하라.
  • DROP TABLE: 데이터셋을 Local SQL에서 연결을 끊어라. 그러면, 자동으로 DROP 된다 (Free 되지는 않는다)
  • CREATE INDEX / DROP INDEX: SQL 인덱스를 만들지 말고, 데이터셋의 Indexes 컬렉션 프로퍼티를 사용하라.
  • CREATE TRIGGER / DROP TRIGGER: SQL 트리거를 만들지 말고, 데이터셋의 이벤트를 사용하라.

Local SQL 엔진은 결과 세트 (Result Set)를 두개 이상을 담는 데이터셋을 지원하지 않는다.

The Local SQL engine supports the INSERT/UPDATE/DELETE SQL commands as transactions and savepoints. Also, it transforms the corresponding SQL commands into TDataSet API calls.

Local SQL 엔진은 INSERT/UPDATE/DELETE SQL 명령을 지원하며 트랜잭션과 저장점(savepoint)도 지원한다. 또한, 해당 SQL 명령을 TDataSet의 API 호출로 변환한다.

The Local SQL engine supports INSERT OR REPLACE, but uses only primary key fields to find a record to replace, when a primary or unique key constraint is violated. Additionally, when only several fields are specified in INSERT OR REPLACE INTO tab (<field list>), the fields that are not specified get NULL values on updating.

Local SQL 엔진은 INSERT 또는 REPLACE를 지원한다. 하지만, 변경(교체)할 레코드를 찾을 때 프라이머리 키나 고유 키 규칙이 지켜지지 않았다면 프라이머리 키 필드(들)만 사용하여 찾는다. 또한 INSERT 또는 REPLACE를 수행할 때 INTO 탭 (<필드 목록>) 안에 명시적으로 지정된 필드(들)만 처리되고 지정되지 않은 필드들에는 모두 NULL 값이 들어간다.

호환성 (Compatibility)

The Local SQL engine uses TDataSet API with some extensions provided by the IFDPhysLocalQueryAdapter interface. FireDAC datasets implement this interface. Optionally, for non-FireDAC datasets, a developer can create a class implementing the interface, and assign its instance to the TFDLocalSQL.DataSets[..].Adapter property.

Local SQL 엔진은 TDataSet API를 사용할 때 IFDPhysLocalQueryAdapter 구현을 제공함으로써 몇가지 확장을 할 수 있다. FireDAC 데이터셋에는 이미 이 인터페이스가 구현되어 있다. 원한다면, FireDAC 데이터셋이 아니어도, 개발자가 해당 인터페이스를 구현하는 클래스를 생성하고, 그 클래스의 인스턴스를 TFDLocalSQL.DataSets[..].Adapter 프로퍼티에 지정할 수도 있다.

Also, to perform the Local SQL operations, a dataset must conform to the following requirements:

또한, Local SQL 작업을 수행하려면, 데이터셋에 아래의 요구사항이 충족되어 있어야만 한다.

작업 요구사항
INSERT

필수:

  • Append 메소드
  • Post 메소드

선택:

  • PSGetKeyFields 프라이머리 키 필드(들)을 반환한다.
UPDATE

필수:

  • Edit 메소드
  • Post 메소드
  • Locate 메소드

선택:

  • PSGetKeyFields 프라이머리 키 필드(들)을 반환한다.
DELETE

필수:

  • Delete 메소드
  • Locate 메소드

선택:

  • PSGetKeyFields 프라이머리 키 필드(들)을 반환한다.
정렬 /
ORDER BY
선택:
  • IFDPhysLocalQueryAdapter.Features가 afIndexFieldNames이면, 데이터셋을 정렬할 때 IFDPhysLocalQueryAdapter.IndexFieldNames 프로퍼티가 사용된다.
필터링 /
WHERE
선택:
  • IFDPhysLocalQueryAdapter.Features가 afRanges이면, 데이터셋을 필터링할 때 IFDPhysLocalQueryAdapter.SetRange 메소드가 사용된다.
  • IFDPhysLocalQueryAdapter.Features가 afFilters이면, 이번에는 Filter 프로퍼티가 사용된다.
저장점
(Savepoint)
필수:
  • IFDPhysLocalQueryAdapter.Features가 afCachedUpdates, afSavePoints이면, 데이터셋을 필터링할 때 IFDPhysLocalQueryAdapter.Savepoint 프로퍼티가 사용된다.
트랜잭션 필수:
  • PSStartTransaction 메소드.
  • PSEndTransaction 메소드.

 

예제 1

The following is a heterogeneous query using SQL Anywhere and Oracle tables and FireDAC TFDQuerys:

이기종 쿼리: SQL Anywhere 테이블 쿼리, 오라클 테이블 쿼리, FireDAC TFDQuery

// SQL Anywhere DB에 있는 "Orders" 테이블에 대한 Connection을 설정하고 쿼리한다
FDConnection1.ConnectionDefName := 'ASA_Demo';
FDConnection1.Connected := True;
FDQuery1.Connection := FDConnection1;
FDQuery1.SQL.Text := 'select * from Orders';
// 데이터셋을 Local SQL 엔진에 연결한다
FDQuery1.LocalSQL := FDLocalSQL1;

// 오라클 DB에 있는 "Order Details" 테이블에 대한 Connection을 설정하고 쿼리한다
FDConnection2.ConnectionDefName := 'Oracle_Demo';
FDConnection2.Connected := True;
FDQuery2.Connection := FDConnection2;
FDQuery2.SQL.Text := 'select * from "Order Details"';
// 데이터셋을 Local SQL 엔진에 연결한다
FDQuery2.LocalSQL := FDLocalSQL1;

// SQLite (인-메모리) Connection을 설정한다
FDConnection3.DriverName := 'SQLite';
FDConnection3.Connected := True;
// Local SQL을 SQLite Connection에 연결한다.
FDLocalSQL1.Connection := FDConnection3;
FDLocalSQL1.Active := True;

// 위에 있는 데이터셋 2개를 대상으로 SELECT 쿼리를 실행한다.
FDQuery3.Connection := FDConnection3;
FDQuery3.SQL.Text := 'SELECT * FROM FDQuery1 LEFT JOIN FDQuery2 ON FDQuery1.OrderID = FDQuery2.OrderID';
FDQuery3.Active := True;

 

예제 2

The following is a heterogeneous query using ADO TADOQuerys and FireDAC TFDQuerys:

이기종 쿼리: ADO TADOQuery 2개와 FireDAC TFDQuery 1개를 사용

"Orders" 테이블에 대한 Connection 설정하고 쿼리한다.
ADOQuery1.SQL.Text := 'select * from Orders';
// 데이터셋을 Local SQL 엔진에 연결한다
with FDLocalSQL1.DataSets.Add do begin
  DataSet := ADOQuery1;
  Name := 'Orders';  // 데이터셋에 이름을 지정한다
end;

"Orders" 테이블에 대한 Connection 설정하고 쿼리한다
ADOQuery2.SQL.Text := 'select * from "Order Details"';
// 데이터셋을 Local SQL 엔진에 연결한다
with FDLocalSQL1.DataSets.Add do begin
  DataSet := ADOQuery2;
  Name := 'Order Details'; // 데이터셋에 이름을 지정한다
end;

// SQLite (인-메모리) Connection을 설정한다
FDConnection1.DriverName := 'SQLite';
FDConnection1.Connected := True;
// Local SQL을 SQLite Connection에 연결한다
FDLocalSQL1.Connection := FDConnection1;
FDLocalSQL1.Active := True;

// 위에 있는 데이터셋 2개를 대상으로 SELECT 쿼리를 실행한다(이때는 데이터셋 이름을 사용한다)
FDQuery1.Connection := FDConnection1;
FDQuery1.SQL.Text := 'SELECT * FROM Orders o LEFT JOIN "Order Details" od ON o.OrderID = od.OrderID';
FDQuery1.Active := True;

 

기타 참고

예제

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

  • Kori changed the title to [DocWiki 번역] Local 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...

중요한 정보

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