我有一个使用ADO的Delphi 2010应用程序来支持可以是SQL Server或MS Access的数据库。使用参数化查询将SQL发送到数据库时,可以正确处理日期表示中的差异。但我偶尔也需要形成动态SQL并将其发送到数据库。
有没有办法让我的日期的TADOConnection格式成为适合当前数据库的文本字符串,或者询问连接以了解我应该如何格式化日期?否则,我将无法构建提供程序名称和日期格式化函数的表。
答案 0 :(得分:3)
您也应该能够使用动态sql参数。我已经在我自己的OPF框架的几个版本中完成了这个。
只需使用参数编写SQL语句,将其作为字符串分配给TAdoQuery(或TAdoCommand)的SQL文本。然后,组件应解析您的文本并为您设置参数集合。之后,您应该能够将值分配给参数并调用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函数负责几次转换。它已在所使用的TCustomDataSet类后代的ADO版本中实现,以处理具有不同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;
答案 1 :(得分:2)
拉里,我会给你一个SQL Server部分的答案。
您可以使用sys.syslanguages
系统视图获取有关sql server中安装的语言的信息,此视图返回的列之一称为dateformat
,表示日期顺序,例如, DMY。
还使用@@langid
(返回当前正在使用的语言的本地语言标识符(ID)。)函数,您可以编写类似这样的函数来获取Sql Server使用的当前日期格式。
select dateformat from sys.syslanguages where langid=@@langid
所以现在你将有一个字符串,你可以在delphi中解析它来格式化你的日期。
另一个选择是选择一种预定义的SQL Server格式,并使用SQL语句中的CONVERT
函数将字符串转换为日期。
检查此样本使用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));
答案 2 :(得分:0)
尝试使用ODBC日期转义序列,SQL Server和Access OLEDB提供程序可能支持该序列。例如:
{d '2011-01-14'}
答案 3 :(得分:0)
正如Marjan建议的那样,你应该总是使用参数。 (尝试搜索SQL注入)
使用参数的另一个原因是查询计划可以在sql server上重用。 如果生成的第一个语句是来自客户的SELECT *&gt;'2010-12-21',并且生成的下一个州语言是来自客户的SELECT *,其中创建了&gt;'2010-12-22',则生成/编译查询优化器/计划两次(不同的声明)。但如果该语句两次都是SELECT *来自客户创建的&gt; ?,则重新使用该计划 - &gt; (稍微)降低SQL服务器上的压力。
我只是不是一个快速而肮脏的解决方案我尝试的所有SQL(实现)(我没有尝试Access)可以接受并理解ISO日期格式(例如'2010-12-21')