4-1. DML 생성 함수 각 폼마다 일일이 모든 코드를 새로 작성해도 되지만 공용으로 사용되는 코드들을 모아서 부모폼을 만들고 상속받아서 사용하면 코딩해아할 양을 많이 줄일 수 있다. TBufDataset의 경우 따로 SQL을 넣어둘 속성이 없기때문에 일일이 조회용과 데이터 처리용 SQL을 만들어줘야한다. 본 예제에서는 간단하게 TField의 ProviderFlags를 활용해서 자동으로 데이터 처리용 SQL 구문을 생성한다. 일종의 편법이라고 볼 수도 있겠지만 어렵고 복잡하게 만드는걸 별로 좋아하지 않아서...^^ 규칙은 간단하다. ProviderFlags의 pfInWhere가 설정되어있으면 등록가능한 필드, pfInUpdate가 설정되어있으면 수정가능한 필드, 그리고 pfInKey가 설정되어있으면 수정이나 삭제시 사용되는 WHERE 조건의 키값이 되는 것이다. 상속용 부모폼에서 사용할 수 있게 DataModule에 DML 생성 함수 추가한다. 그리고 메인화면의 버튼과 각 폼을 생성할 때 권한 처리용 변수도 DataModule에 추가한다.
      TdmSIMLaz = class(TDataModule)
      :
      :
      public
      :
      :
        u_auth_n, // 등록권한
        u_auth_m, // 수정권한
        u_auth_d, // 삭제권한
        u_auth_p, // 인쇄권한
        u_auth_a, // 전체권한

        u_btn_v, // 조회버튼
        u_btn_n, // 등록버튼
        u_btn_d, // 삭제버튼
        u_btn_s: Boolean; // 저장버튼

        function UF_SIMLazDML(ADataSet: TCustomBufDataset;
          AName: string; AType: TUpdateKind): string;
      :
      :
    // DML 생성
    function TdmSIMLaz.UF_SIMLazDML(ADataSet: TCustomBufDataset;
      AName: string; AType: TUpdateKind): string;

      function LF_Value(AField: TField; AIsOld: Boolean = False): string;
      begin
        if AField.IsNull then Result := 'NULL'
        else
        begin
          case AField.DataType of
            ftDate:
              if AIsOld then
                Result := QuotedStr(FormatDateTime('yyyy-mm-dd', AField.OldValue))
              else
                Result := QuotedStr(FormatDateTime('yyyy-mm-dd', AField.AsDateTime));

            ftTime:
              if AIsOld then
                Result := QuotedStr(FormatDateTime('hh:nn:ss', AField.OldValue))
              else
                Result := QuotedStr(FormatDateTime('hh:nn:ss', AField.AsDateTime));

            ftDateTime, ftTimeStamp: //, ftOraTimeStamp
              if AIsOld then
                Result := QuotedStr(FormatDateTime('yyyy-mm-dd hh:nn:ss', AField.OldValue))
              else
                Result := QuotedStr(FormatDateTime('yyyy-mm-dd hh:nn:ss', AField.AsDateTime));

            ftSmallint, ftInteger, ftLargeInt:
              if AIsOld then Result := IntToStr(AField.OldValue)
              else Result := IntToStr(AField.Value);

            ftFloat, ftCurrency, ftBCD:
              if AIsOld then Result := FloatToStr(AField.OldValue)
              else Result := FloatToStr(AField.Value);

          else
            if AIsOld then Result := QuotedStr(AField.OldValue)
            else Result := QuotedStr(AField.AsString);
          end;
        end;
      end;

    var
      i: Int32;
      l_ValueFlag, l_KeyFlag: Boolean;
      l_Values, l_Keys, t, l_Fields, l_FieldName: string;
    begin
      Result := '';
      if AName = '' then Exit;

      l_Keys := '';
      l_Fields := '';
      l_Values := '';
      l_KeyFlag := False;
      l_ValueFlag := False;

      with ADataSet do
      begin
        for i := 0 to Fields.Count - 1 do
        begin
          l_FieldName := LowerCase(Fields[i].FieldName);

          if (pfInWhere in Fields[i].ProviderFlags) and (AType = ukInsert) then
          begin
            if l_ValueFlag then t := ',' else t := ' ';
            l_Fields := l_Fields + t + l_FieldName;
            l_Values := l_Values + t + LF_Value(Fields[i]);
            l_ValueFlag := True;
          end
          else if (pfInUpdate in Fields[i].ProviderFlags) and (AType = ukModify) then
          begin
            if Fields[i].OldValue <> Fields[i].Value then
            begin
              if l_ValueFlag then t := ',' else t := ' ';
              l_Values := l_Values + t + l_FieldName + ' = ' + LF_Value(Fields[i]);
              l_ValueFlag := True;
            end;
          end;

          if (pfInKey in Fields[i].ProviderFlags) and (AType in [ukDelete, ukModify]) then
          begin
            if l_KeyFlag then t := ' AND ' else t := ' ';
            l_Keys := l_Keys + t + l_FieldName + ' = ' + LF_Value(Fields[i], True);
            l_KeyFlag := True;
          end;
        end;
      end;

      case AType of
        ukInsert:
          Result := 'INSERT INTO ' + AName + ' (' + l_Fields + ' ) VALUES (' + l_Values + ' )';

        ukDelete:
          Result := 'DELETE FROM ' + AName + ' WHERE' + l_Keys;

        ukModify:
          if l_Values <> '' then
            Result := 'UPDATE ' + AName + ' SET' + l_Values + ' WHERE' + l_Keys;
      end;
    end;