Форматировать дату в соответствии с провайдером ADO - PullRequest
1 голос
/ 13 января 2011

У меня есть приложение Delphi 2010, использующее ADO для поддержки базы данных, которая может быть либо SQL Server, либо MS Access. При отправке SQL в базу данных с использованием параметризованных запросов различия в представлении даты обрабатываются корректно. Но иногда мне нужно сформировать динамический SQL и отправить его в базу данных.

Можно ли каким-либо образом преобразовать мою дату в формате TADOConnection в текстовую строку, соответствующую текущей базе данных, или опросить соединение, чтобы узнать, как мне отформатировать дату? В противном случае я застрял в создании таблицы имен поставщиков и функций форматирования даты.

Ответы [ 4 ]

3 голосов
/ 14 января 2011

Вы также должны иметь возможность использовать параметры с динамическим sql.Я сделал это в нескольких версиях моей собственной инфраструктуры OPF.

Просто напишите оператор SQL, используя параметры, назначьте его в виде строки в тексте SQL TAdoQuery (или TAdoCommand).Затем компонент должен проанализировать ваш текст и настроить коллекции параметров для вас.После этого вы сможете назначить значения своим параметрам и вызвать Open или Execute ...

Чтобы дать вам представление:

  DS := DatasetClass.Create( self.Connection );
  try
    DS.QueryText := SQL.Text;
    FillSelectParams( DS );
    DS.Open;
    try
      ...
    finally
      DS.Close;
    end;
  finally
    DS.Free;
  end;

, в котором FillSelectParams вызывает следующие FillParamsпроцедура:

procedure TSQLDataManager.FillParams(ADS: TCustomDataset);
var
  i: integer;
  ParamName: string;
  Attr: TCustomDomainAttribute;
  Ref: TCustomDomainObject;
  Value: Variant;
begin
  for i := 0 to ADS.ParamCount - 1 do begin
    Value := Null;
    ParamName := ADS.ParamName[i];
    if ParamName = 'Id' then begin
      ParamName := 'Identity';
    end;
    Attr := CDO.AttrByName[ParamName];
    if Attr <> nil then begin
      Value := ADS.AdjustParamValue( Attr );
    end else begin
      Ref := CDO.ReferenceByName[ParamName];
      if ( Ref <> nil ) and ( Ref.Identity <> C_UnassignedIdentity ) then begin
        Value := Ref.Identity;
      end;
    end;
    if Value <> Null then begin
      ADS.ParamValue[i] := Value;
    end;
  end;
end;

В этом случае значения параметров берутся из объекта пользовательского домена (CDO), но вы можете заменить свой собственный вариант здесь.

Функция AdjustParamValue заботится опара преобразований.Он был реализован в версии ADO используемого потомка класса TCustomDataSet, чтобы заботиться о вариациях компонентов с различными потомками TDataSet, но нигде не используется тип базы данных SQL:

function TADODCDataset.AdjustParamValue(Attr: TCustomDomainAttribute): Variant;
begin
  if Attr is TIdentityAttribute then begin
    if Attr.AsInteger = 0 then begin
      Result := Null;
    end else begin
      Result := Attr.Value;
    end;
  end else if Attr is TBooleanAttribute then begin
    if Attr.AsBoolean then begin
      Result := Integer( -1 );
    end else begin
      Result := Integer( 0 );
    end;
  end else if Attr is TDateTimeAttribute then begin
    if Attr.AsDateTime = 0 then begin
      Result := Null;
    end else begin
      Result := Attr.Value;
    end;
  end else if Attr is TEnumAttribute then begin
    Result := Attr.AsString
  end else begin
    Result := Attr.Value;
  end;
end;
2 голосов
/ 14 января 2011

Ларри, я дам вам ответ на SQL Server Part.

Вы можете использовать системное представление sys.syslanguages для получения информации о языках, установленных на сервере sql, один из столбцов, возвращаемых этим представлением, называется dateformat, которые указывают порядок дат для Например, DMY.

также используя функцию @@langid (которая возвращает идентификатор (ID) локального языка языка, который используется в настоящее время.) Вы можете написать что-то вроде этого, чтобы получить текущий формат даты, используемый Сервер Sql.

select dateformat from sys.syslanguages  where langid=@@langid

так что теперь у вас будет строка, которую вы можете проанализировать в delphi для форматирования вашей даты.

Другой вариант - выбрать один из предопределенных форматов SQL Server и использовать функцию CONVERT в предложении SQL для преобразования строки в дату.

проверьте этот пример, который использует формат ISO для преобразования

//The ISO  format is yyyymmdd so i can use the FormatDateTime function to convert any TdateTime to a Iso format sdatetiem string
DateStr:=FormatDateTime('YYYYMMDD',Now);
//Now construct the sql server sentence
SqlSentence:=Format('UPDATE MyTable SET DateField=CONVERT(DATETIME,%s,112)',QuotedStr(DateStr));
0 голосов
/ 14 января 2011

Как предполагает Марьян, вы должны всегда использовать параметры . (попробуйте поискать SQL-инъекцию)

Еще одна причина использования параметров заключается в том, что планы запросов можно повторно использовать на сервере sql. Если первый сгенерированный оператор SELECT * от клиента, где он был создан> '2010-12-21', а следующий сгенерированный оператор SELECT * от клиента, где он был создан> '2010-12-22', оптимизатор / план запроса генерируется / компилируется оба раза (другое утверждение). Но если оператором оба раза являются SELECT * от клиента, где он был создан>?, План используется повторно -> (немного) с меньшим давлением на сервере SQL.

Я просто не хочу быстрого и грязного решения, все SQL (реализации), которые я пробовал (я не пробовал Access), могут принять и понять формат даты ISO (например, '2010-12-21')

0 голосов
/ 14 января 2011

Попробуйте использовать escape-последовательность даты ODBC, которая может поддерживаться поставщиками SQL Server и Access OLEDB.Например:

{d '2011-01-14'}
...