无法在delphi ADO查询中找到记录

时间:2014-05-29 03:12:36

标签: sql oracle delphi

我无法使用PK找到TADOQuery中的任何记录。首先,我试图使用标准的Locate方法:

PPUQuery.Locate('ID', SpPlansQuery['PPONREC'], []);

它始终返回False,但是手动搜索(传递与ID匹配的PPONREC的整个查询非常慢),找到所需的行。我尝试使用loPartialKey并将查询的CursorLocation切换为clUseServer,但它没有帮助。

接下来,我尝试过滤我的PPUQuery

PPUQuery.Filter := 'ID = ' + VarToStr(SpPlansQuery['PPONREC']);
PPUQuery.Filtered := True;
PPUQuery.First;

但在此之后,PPUQuery.EofTruePPUQuery.RecordCount等于0

PPUQuery字段列表:

object PPUQueryNUM: TFMTBCDField
  DisplayLabel = #1053#1086#1084#1077#1088
  FieldName = 'NUM'
  ReadOnly = True
  Precision = 38
  Size = 0
end
object PPUQueryINUM: TFMTBCDField
  DisplayLabel = #1053#1086#1084#1077#1088' '#1062#1052#1050
  FieldName = 'INUM'
  ReadOnly = True
  Precision = 38
  Size = 0
end
object PPUQueryONUM: TFMTBCDField
  DisplayLabel = #1055#1086#1088#1103#1076#1082#1086#1074#1099#1081' '#1085#1086#1084#1077#1088
  FieldName = 'ONUM'
  ReadOnly = True
  Precision = 38
  Size = 0
end
object PPUQueryDRAWING: TStringField
  DisplayLabel = #1053#1086#1084#1077#1088' '#1095#1077#1088#1090#1077#1078#1072
  FieldName = 'DRAWING'
  ReadOnly = True
  Size = 50
end
object PPUQueryWEIGHT: TFloatField
  DisplayLabel = #1042#1077#1089
  FieldName = 'WEIGHT'
  ReadOnly = True
end
object PPUQueryTITLE: TStringField
  DisplayLabel = #1047#1072#1075#1086#1083#1086#1074#1086#1082
  FieldName = 'TITLE'
  ReadOnly = True
  Size = 200
end
object PPUQueryPRODUCER: TFMTBCDField
  DisplayLabel = #1055#1088#1086#1080#1079#1074#1086#1076#1080#1090#1077#1083#1100
  FieldName = 'PRODUCER'
  ReadOnly = True
  Precision = 38
  Size = 0
end
object PPUQueryGRAPH: TStringField
  DisplayLabel = #1043#1088#1072#1092#1080#1082
  FieldName = 'GRAPH'
  ReadOnly = True
  Size = 200
end
object PPUQueryNOTE: TStringField
  DisplayLabel = #1055#1088#1080#1084#1077#1095#1072#1085#1080#1077
  FieldName = 'NOTE'
  ReadOnly = True
  Size = 1024
end
object PPUQueryUPDATED: TDateTimeField
  DisplayLabel = #1054#1073#1085#1086#1074#1083#1105#1085
  FieldName = 'UPDATED'
  ReadOnly = True
end
object PPUQueryRELDATE: TDateTimeField
  DisplayLabel = #1044#1072#1090#1072' '#1086#1082#1086#1085#1095#1072#1085#1080#1103' '#1080#1079#1075#1086#1090#1086#1074#1083#1077#1085#1080#1103
  FieldName = 'RELDATE'
  ReadOnly = True
end
object PPUQueryID: TFMTBCDField
  FieldName = 'ID'
  ReadOnly = True
  Visible = False
  Precision = 38
  Size = 0
end
object PPUQueryNUM_OF: TFMTBCDField
  FieldName = 'NUM_OF'
  ReadOnly = True
  Visible = False
  Precision = 38
  Size = 0
end
object PPUQueryORDER_ID: TFMTBCDField
  FieldName = 'ORDER_ID'
  Precision = 38
  Size = 0
end
object PPUQueryPLAN_ID: TFMTBCDField
  FieldName = 'PLAN_ID'
  Precision = 38
  Size = 0
end
object PPUQueryCNUM: TStringField
  FieldName = 'CNUM'
  Size = 50
end
object PPUQueryCADEP: TFMTBCDField
  FieldName = 'CADEP'
  Precision = 38
  Size = 0
end
object PPUQueryMATERIAL: TFMTBCDField
  FieldName = 'MATERIAL'
  Precision = 38
  Size = 0
end
object PPUQueryARTICLE: TFMTBCDField
  DisplayLabel = #1057#1090#1072#1090#1100#1103
  FieldName = 'ARTICLE'
  Precision = 38
  Size = 0
end
object PPUQueryDEPTH: TFloatField
  FieldName = 'DEPTH'
end
object PPUQueryPAINT: TFMTBCDField
  FieldName = 'PAINT'
  Precision = 38
  Size = 0
end
object PPUQueryBSS: TFMTBCDField
  FieldName = 'BSS'
  Precision = 38
  Size = 0
end
object PPUQueryQNUM: TFMTBCDField
  DisplayLabel = #1054#1095#1077#1088#1077#1076#1100
  FieldName = 'QNUM'
  Precision = 38
  Size = 0
end
object PPUQuerySERVICE: TFMTBCDField
  FieldName = 'SERVICE'
  Precision = 38
  Size = 0
end
object PPUQueryCONTINUE: TFMTBCDField
  FieldName = 'CONTINUE'
  Precision = 38
  Size = 0
end
object PPUQueryADVANCED: TFMTBCDField
  FieldName = 'ADVANCED'
  Precision = 38
  Size = 0
end
object PPUQueryMETIZ: TFMTBCDField
  FieldName = 'METIZ'
  Precision = 38
  Size = 0
end
object PPUQueryID_1: TFMTBCDField
  FieldName = 'ID_1'
  Precision = 38
  Size = 0
end
object PPUQueryTITLE_1: TStringField
  DisplayLabel = #1057#1090#1072#1090#1100#1103
  FieldName = 'TITLE_1'
end
object PPUQueryORD: TFMTBCDField
  FieldName = 'ORD'
  Precision = 38
  Size = 0
end
object PPUQueryID_2: TFMTBCDField
  FieldName = 'ID_2'
  Precision = 38
  Size = 0
end
object PPUQueryTITLE_2: TStringField
  DisplayLabel = #1052#1072#1090#1077#1088#1080#1072#1083
  FieldName = 'TITLE_2'
  Size = 100
end
object PPUQueryID_3: TFMTBCDField
  FieldName = 'ID_3'
  Precision = 38
  Size = 0
end
object PPUQueryCA: TFMTBCDField
  FieldName = 'CA'
  Precision = 38
  Size = 0
end
object PPUQueryTITLE_3: TStringField
  DisplayLabel = #1047#1072#1082#1072#1079#1095#1080#1082
  FieldName = 'TITLE_3'
  Size = 100
end
object PPUQueryID_4: TFMTBCDField
  FieldName = 'ID_4'
  Precision = 38
  Size = 0
end
object PPUQueryCA_1: TFMTBCDField
  FieldName = 'CA_1'
  Precision = 38
  Size = 0
end
object PPUQueryTITLE_4: TStringField
  DisplayLabel = #1055#1088#1086#1080#1079#1074#1086#1076#1080#1090#1077#1083#1100
  FieldName = 'TITLE_4'
  Size = 100
end
object PPUQueryID_5: TFMTBCDField
  FieldName = 'ID_5'
  Precision = 38
  Size = 0
end
object PPUQueryARTICLE_1: TFMTBCDField
  FieldName = 'ARTICLE_1'
  Precision = 38
  Size = 0
end
object PPUQueryMATERIAL_1: TFMTBCDField
  FieldName = 'MATERIAL_1'
  Precision = 38
  Size = 0
end
object PPUQueryPRODUCER_1: TFMTBCDField
  FieldName = 'PRODUCER_1'
  Precision = 38
  Size = 0
end
object PPUQueryWEIGHT_1: TFloatField
  FieldName = 'WEIGHT_1'
end
object PPUQueryINUM_1: TFMTBCDField
  FieldName = 'INUM_1'
  Precision = 38
  Size = 0
end
object PPUQueryQNUM_1: TFMTBCDField
  FieldName = 'QNUM_1'
  Precision = 38
  Size = 0
end

底层数据库是Oracle 9,ID类型为INTEGER,是表TPORDER_CMK的PK。 PPUQuery.SQL是:

SELECT tp.*, la.*, lm.*, ld.*, ld1.*, to_cmk.*
  FROM ppu_plan.tporder_cmk tp
       JOIN PPU_PLAN.LARTICLES la
          ON TP.ARTICLE = LA.ID
       JOIN PPU_PLAN.LMATERIAL lm
          ON TP.MATERIAL = lm.id
       JOIN PPU_PLAN.LCADEP ld
          ON TP.CADEP = LD.ID
       JOIN PPU_PLAN.LCADEP ld1
          ON TP.PRODUCER = LD1.ID
       JOIN PPU_PLAN.TORDER_CMK to_cmk
          ON TP.order_id=TO_cmk.ID
WHERE TP.PLAN_ID = :pplan_id

TPORDER_CMK的DDL脚本:

CREATE TABLE PPU_PLAN.TPORDER_CMK
(
  ID        INTEGER                             NOT NULL,
  ORDER_ID  INTEGER                             NOT NULL,
  PLAN_ID   INTEGER                             NOT NULL,
  NUM       INTEGER,
  ONUM      INTEGER,
  CNUM      VARCHAR2(50 BYTE),
  DRAWING   VARCHAR2(50 BYTE),
  TITLE     VARCHAR2(200 BYTE),
  NUM_OF    INTEGER                             DEFAULT 0,
  CADEP     INTEGER,
  WEIGHT    FLOAT(126),
  MATERIAL  INTEGER,
  ARTICLE   INTEGER,
  DEPTH     FLOAT(126),
  PRODUCER  INTEGER                             NOT NULL,
  INUM      INTEGER,
  PAINT     INTEGER                             NOT NULL,
  BSS       INTEGER                             NOT NULL,
  QNUM      INTEGER                             DEFAULT NULL,
  SERVICE   INTEGER                             NOT NULL,
  CONTINUE  INTEGER                             NOT NULL,
  GRAPH     VARCHAR2(200 BYTE),
  ADVANCED  INTEGER                             NOT NULL,
  NOTE      VARCHAR2(1024 BYTE),
  UPDATED   DATE                                DEFAULT SYSDATE               NOT NULL,
  RELDATE   DATE,
  METIZ     INTEGER                             DEFAULT 0                     NOT NULL
)
TABLESPACE WEB
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          80K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOLOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
NOMONITORING;


CREATE INDEX PPU_PLAN.TPORDER_CMK_IDX ON PPU_PLAN.TPORDER_CMK
(ORDER_ID, PLAN_ID, NUM, ONUM, CADEP, 
MATERIAL, ARTICLE, PRODUCER, PAINT, BSS, 
SERVICE, CONTINUE, GRAPH, ADVANCED, UPDATED, 
RELDATE, METIZ)
LOGGING
TABLESPACE WEB
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOPARALLEL;


CREATE UNIQUE INDEX PPU_PLAN.TPORDER_CMK_PK ON PPU_PLAN.TPORDER_CMK
(ID)
NOLOGGING
TABLESPACE WEB
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          80K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOPARALLEL;


CREATE OR REPLACE TRIGGER PPU_PLAN.TRPORDER_CMK
    BEFORE INSERT ON PPU_PLAN.TPORDER_CMK     FOR EACH ROW
WHEN (
NEW.ID IS NULL
      )
DECLARE NID INTEGER;
    BEGIN
        IF (:new.ID = NULL) THEN
        BEGIN
            SELECT SPORDER_CMK.NEXTVAL INTO NID FROM DUAL;
            :new.ID := NID;
        END;
        END IF;
    END;
/


ALTER TABLE PPU_PLAN.TPORDER_CMK ADD (
  CONSTRAINT TPORDER_CMK_PK
  PRIMARY KEY
  (ID)
  USING INDEX PPU_PLAN.TPORDER_CMK_PK
  ENABLE VALIDATE);

SpPlansQuery['PPONREC']TFmtBcdField,但即使按字面意义指定值(例如18323)也无济于事。

我之前的问题(Cannot assign data to client dataset)包含的信息可能有助于找出我想要实现的目标。

接下来我应该尝试什么以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我找到了我讨厌的临时解决方案,因为它耗费内存并且比我想要的慢3倍。此外,我为过多地回答我自己的问题而道歉,但这是我找到的最佳解决方案。

我必须传递PPUQuery并使用我想要的值构建TDictionary<Integer, Variant>。接下来,我查询字典而不是使用TADOQuery.Locate

uses Generics.Collections;

procedure ReFillDataSet;
const
  // IMPORTANT: check that fields count in next 2 lines would be the same
  FieldsStr1 = 'FIELD_1_PPU;FIELD_2_PPU;FIELD_3_PPU';
  FieldsStr2 = 'FLD_1;FLD_2;FLD_3';
var
  Deleted, Changed: Boolean;
  FieldValues1, FieldValues2: Variant;
  Idx1, Idx2: TDictionary<Integer, Variant>
begin
  ComparisonDataSet.DisableControls;
  ComparisonDataSet.EmptyDataSet;
  // building indexes
  Idx1 := TDictionary<Integer, Variant>.Create;
  Idx1.Clear;
  PPUQuery.First;
  while not PPUQuery.Eof do begin
    Idx1.Add(PPUQuery['ID'], PPUQuery[FieldsStr2]);
    PPUQuery.Next;
  end;
  Idx2 := TDictionary<Integer, Variant>.Create;
  Idx2.Clear;
  SpPlansQuery.First;
  while not SpPlansQuery.Eof do begin
    Idx2.Add(SpPlansQuery['PPONREC'], Null);
    SpPlansQuery.Next;
  end;
  // deleted and changed records
  SpPlansQuery.First;
  while not SpPlansQuery.Eof do
  begin
    FieldValues1 := SpPlansQuery[ReplaceStr(FieldsStr1, '_PPU', '')];
    //Deleted := not PPUQuery.Locate('ID', SpPlansQuery['PPONREC'], []);
    Deleted := not Idx1.ContainsKey(SpPlansQuery['PPONREC']);
    if not Deleted then
    begin
      FieldValues2 := Idx1[SpPlansQuery['PPONREC']];
      Changed := False;
      // count fields
      Fields := TList.Create;
      try
        ComparisonDataSet.GetFieldList(Fields, FieldsStr1);
        for J := 0 to Fields.Count - 1 do
        begin
          if Changed then
            System.Break;
          Changed := Changed or (FieldValues1[J] <> FieldValues2[J]);
        end;
      finally
        Fields.Free;
      end;
    end;
    if Deleted or Changed then
    begin
      ComparisonDataSet.Append;
      ComparisonDataSet[ReplaceStr(FieldsStr1, '_PPU', '')] := FieldValues1;
      if Deleted then
        ComparisonDataSet['Oper'] := 2
      else begin
        ComparisonDataSet['Oper'] := 1;
        ComparisonDataSet[FieldsStr1] := FieldValues2;
      end;
      ComparisonDataSet.Post;
    end;
    SpPlansQuery.Next;
  end;
  // added records
  PPUQuery.First;
  while not PPUQuery.Eof do begin
    if not {SpPlansQuery.Locate('PPONREC', PPUQuery['ID'], [])} Idx2.ContainsKey(PPUQuery['ID']) then begin
      ComparisonDataSet.Append;
      ComparisonDataSet[FieldsStr1] := PPUQuery[FieldsStr2];
      ComparisonDataSet['Oper'] := 0;
      ComparisonDataSet.Post;
    end;
    PPUQuery.Next;
  end;
  Idx1.Free;
  Idx2.Free;
  ComparisonDataSet.First;
  ComparisonDataSet.EnableControls;
end;