Kori 4월 20일, 2022에 포스트됨 공유하기 4월 20일, 2022에 포스트됨 Docwiki에 있는 "Editing Questions (FireDAC)"을 번역한 글: 번역일: 2022년 4월 18일 위로 가기: [DocWiki 번역] FAQ (FireDAC) 데이터 편집하기 관련 질문과 답변을 정리한 목록이다. Q1: "[FireDAC][DApt]-400. Update command updated [0] instead of [1] record"는 무슨 뜻인가? A: 이 에러는 FireDAC 안에 float / double / single / date / datetime / time 또는 기타 이와 같은 테이블(table) 필드(field)가 있을 때 종종 발생한다. 이런 필드들은 WHERE 절에서 정확도 손실(precision loss)의 영향을 받는다. 정확도 손실은 애플리케이션에서 파라미터에 값을 할 때 할 때 생길 수 있다. 그 결과, WHERE 절에서 레코드를 하나로 반환하지 못하게 된다. FireDAC이 WHERE 안에 이런 필드를 넣는 방식은 UpdateOptions.UpdateMode에 따라 정해진다. 때때로 이 오류는 upWhereKeyOnly 일때 나타난다. 당신이 upWhereKeyOnly를 명시했더라도, FireDAC에서 여전히 upWhereAll을 사용할 수도 있는데 PK 필드가 정의되지 않았을 때 그럴 수 있다. 다음과 같은 경우에 PK 필드가 정의되지 않게 된다: FetchOptions.Items에서 fiMeta가 빠져있을 때; 또는 a table in SQL 안에 들어 있는 테이블에 프라이머리 키(primary key)를 정의되어 있지 않았을 때; 또는 UpdateOptions.KeyFields가 비어있을 때; 또는 TField 중 어느 것에도 ProviderFlags 프로퍼티 안에 pfInKey가 들어있지 않을 때. 또 다른 이유가 있는데, (SQL Server, PostgreSQL)과 같은 몇몇 DBMS에서 테이블에 데이터를 변경하는 트리거(trigger)가 걸려 있을 때 발생할 수 있다. SQL 서버인 경우라면 트리거 코드 맨 위에 SET NOCOUNT ON를 넣어라. PostgreSQL 인 경우라면 UpdateOptions.CountUpdatedRecords에 False를 지정하라. Q2: TFDUpdateSQL는 언제 사용하는 것인가? A: SQL 명령(command) 원본이 단순 SELECT 명령이거나 또는 조인(join) SELECT 명령이지만 프라이머리 키(primary key) 필드를 유지할 때, FireDAC은 업데이트하는 SQL 명령(command)을 자동으로 만들어 낸다. 따라서, TFDUpdateSQL 사용은 필수가 아니라 선택이다. TFDUpdateSQL가 필요한 경우는 다음과 같다: SQL 명령(command) 원본이 SELECT 명령이 아닐 때 (예를 들면, 결과 세트를 반환하는 저장 프로시저인 경우). SQL 명령(command) 원본에서 프라이머리 키(primary key)를 유지하지 않을 때 (예를 들면, 여러 테이블을 조인하는데, DISTINCT 또는 GROUP BY 절이 들어있는 경우). 표준이 아닌 업데이트 SQL 명령을 애플리케이션에서 사용해야 할 때 (예를 들면, 애플리케이션에서 저장 프로시저를 사용하여 업데이트를 전송 즉 post 할 때). Q3: FDUpdateSQL 안에 있는 SQL에서 매크로(macro)를 사용하는 것이 가능한가? A: 아래 코드를 사용하라: FDUpdateSQL1.Commands[arInsert].MacroByName('MacroName').Value := 'value'; Q4: 캐시된 업데이트(CachedUpdates) 모드에서, 삽입되는 레코드들을 다신 전송(post)하도록 ApplyUpdates를 한번 넘게 호출해야 하는 이유는 무엇인가? A: ApplyUpdate를 호출한 후에, CommitUpdates를 호출해야 한다. CommitUpdates가 호출되고 나면, 모든 변경이 내부 캐시(internal cache)에서 제거된다. Q5: 마스터-디테일 관계에서, 마스터 TFDQuery가 스크롤(scroll) 또는 전송(post)된 후에도 디테일 TFDQuery가 새로고침(refresh)되지 않도록 하는 방법은? A: 2가지 방법이 있다: 마스터-디테일 관계를 당신이 원하는 데로 구현한다. 그러려면, TDataSource.OnDataChange 이벤트 핸들러를 추가해야 한다. 이것이 "표준" 방식이다. 중앙집중식 캐시된 업데이트(centralized cached updates)를 사용한다. Q6: 데이터셋의 레코드를 제거할 때 데이터베이스에서 이 레코드가 지워지지 않도록 하는 방법은? A: 당신은 내부 데이터셋 데이터 저장소에서 직접 작업할 수 있다. TFDDataSet.Table 프로퍼티를 사용하여 여기에 접근할 수 있다. 예를 들면, 인덱스 3을 가진 행(row)을 삭제(delete)하려면 아래와 같이 한다: FDQuery1.UpdateCursorPos; FDQuery1.GetRow.Free; FDQuery1.UpdateCursorPos; FDQuery1.Resync([]); 그리고 결국에는 CachedUpdates 모드를 사용할 수 있다. 데이터셋을 캐시된 업데이트(cached updates) 모드로 지정하라. 그리고 레코드를 삭제(delete)하고, CommitUpdates를 호출하라. Q7: FireDAC을 사용하여, ATable.UpdateToDataset(BTable , 'mykey', [mtufEdit, mtufAppend])를 생성하는 방법은? A: TFDDataSet.CopyDataSet 메소드를 아래 옵션들과 함께 사용하라: [coAppend] - ASource (에 있던 그대로) 에서 모든 레코드를 가져와서 덛붙인다(append); [coEdit] - 기존의 키 값(key value)을 가진 레코드 만 편집(edit)한다; [coAppend, coEdit] - 기존의 키 값(key value)을 가진 레코드를 편집(edit)하고, 기존에 키가 없는 레코드는 덛붙인다(append). Q8: ftGUID 필드에 값을 할당(assign)하는 방법은? A: 아래 코드를 사용하라: (AMemTable.FieldByName('Field1') as TGUIDField).AsGuid := aGUID; Q9: 데이터셋(dataset) 필드(field)에 기본 값(default value)을 지정하는 방법은? A: TField.DefaultExpression 프로퍼티에 표현식(expression)을 할당하라. Q10: TField.DefaultExpression 프로퍼티는 TField.CustomConstraint와 같은 방식으로 지원되나? 이 기본 표현식(default expression)에 적힌 내용은 필드의 기본 값(default value)의 효력과 같은가? A: 그렇다, 단, 필드가 만약 일반(normal) 결과 세트(result set) 필드일 때 그렇다. 만약 필드가 fkInternalCalc 이라면, then the result of the DefaultExpression의 결과는 필드(field) 값(value)으로 사용되고 다른 계산된 필드(calculated field)와 마찬가지로 업데이트 될 것이다. Q11: {fn DAYOFMONTH({fn CURDATE()})} 은 올바른 표현식(expression)인가? A: 아니다. 당신은 지금 FireDAC의 이스케이프 함수(escape function)를 사용하고 있다. 이것은 오직 SQL 명령(command) 안에서만 작동한다. 제약조건(constraint)이나 기본 값(default value)과 같은 표현식(expression) 안에서는 작동하지 않는다. 당신은 FireDAC의 표현식 평가기(expression evaluator)가 지원하는 함수(function)와 구문(syntax) 만을 사용해야 한다: DAYOFMONTH(CURDATE()) 또한, 이와 같은 함수(function)를 사용하려면, uADStanExprFuncs 유닛을 당신의 애플리케이션에 포함(include)해야 한다. Q12: 데이터셋(dataset)의 불리언(Boolean) 필드(field)에 기본 값(default value)을 명시하는 방법은? A: 데이터셋(dataset)의 필드(field)에 기본 값(default value)을 명시하려면 TField.DefaultExpression 프로퍼티에 표현식(expression)을 할당(assign)하라. 불리언(Boolean) 필드(field)에 기본 값(default value)을 할당하려면, False를 할당하고 싶으면 문자열 F, FA, FAL, FALS, FALSE 중 하나를 넣어라. True 인 경우에도 마찬가지 방법으로 할 수 있다. Q13: TField.CustomConstraint 할당(assign)하기가 작동하지 않는다. 뭐가 잘못되었나? Q: 제약조건(constraint) 추가하기를 다음 방식으로 했다: FDQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1'; FDQuery.UpdateConstraints; FDQuery.Table.Constraints.Check(FDQuery.GetRow(), rsModified, ctAtEditEnd); 작동하지 않는다. 그리고 예외(exception)가 생기지도 않는다. A: 괜찮다 (아래에서 설명). Q: 그러나: FDQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1'; FDQuery.UpdateConstraints; FDQuery.Table.Constraints.Check(FDQuery.GetRow(), rsModified, ctAtEditEnd); 작동한다! 왜 그런가? A: 역시 괜찮다. Q: ctAtEditEnd와 ctAtColumnChange은 정확히 무슨 뜻인가? A: 이 열거형(enum)은 FireDAC이 제약조건(constraint)을 점검하는 시점을 명시한다: ctAtEditEnd - Post가 호출 될 때 ctAtColumnChange - 필드(field)의 값(value)이 변경될 때 아래 설명을 보자: FDQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1'; 위 코드는 필드(field)-수준 제약조건을 추가한다. 이것은 오직 ctAtColumnChange 이벤트에서만 점검할 수 있다. FDQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1'; 위 코드는 레코드(record)-수준 제약조건을 추가한다. 이것은 오직 ctAtEditEnd 이벤트에서만 점검할 수 있다. 인용하기 이 댓글 링크 다른 사이트에 공유하기 더 많은 공유 선택 사항
Recommended Posts
이 토의에 참여하세요
지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.