我们正在将我们的一个项目从Delphi XE升级到XE8。我们的审计代码使用MSSQL(在此实例中为2012)数据库中的TIMESTAMP字段,并从表中选择使用它作为WHERE子句中的参数。
我们现在不再使用以下代码获得任何结果:
procedure TForm2.Button1Click(Sender: TObject);
begin
ADODataset1.CommandText := 'SELECT * FROM CURRENCYAUDIT';
ADODataset2.CommandText := 'SELECT * FROM CURRENCYAUDIT WHERE Audit_Timestamp = :Timestamp';
ADODataset2.Parameters.Refresh;
ADODataset1.Open;
if ADODataset1.FieldByName('audit_timestamp').IsNull or ADODataset1.IsEmpty then
begin
showmessage('nothing to compare');
end;
ADODataset2.Parameters[0].Value := ADODataset1.FieldByName('audit_timestamp').Value;
ADODataset2.Open;
caption := inttostr(ADODataset2.RecordCount);
end;
其中CurrencyAudit是包含notnull timestamp audit_timestamp字段的任何旧MSSQL表。
表单的标题为0,未显示任何消息。
知道如何才能让它发挥作用吗?尝试AsString(无意义字符串,0结果),AsSQLTimestamp(参数不接受)和AsBytes(0返回)。不幸的是,.Value
的返回仅仅是作为字节'变体数组的变换。这对于可视化/查看它是什么并没有帮助。
编辑:运行它.AsBytes并在调试器中查看我可以看到XE verison返回0,0,0,0,0,8,177,22而XE8返回17,32,0,0 ,0,0,0,0。检查(实际)数据库的其他字段显示记录是相同的。看起来像从DB中读取TIMESTAMPs的错误
答案 0 :(得分:1)
我使用了两个AdoQueries。以下在D7中对我来说很好,在AdoQuery2中正确返回1行,但在XE8中有0个记录,因此显然有与您遇到的相同的XE8问题。
var
S : String;
V : Variant;
begin
AdoQuery1.Open;
S := AdoQuery1.FieldByName('ATimeStamp').AsString;
V := AdoQuery1.FieldByName('ATimeStamp').AsVariant;
Caption := S;
AdoQuery2.Parameters.ParamByName('ATimeStamp').Value := V;
AdoQuery2.Open;
只是为了测试,我在同一服务器表上运行我的AdoQuery1和AdoQuery2。
更新我在你的答案工作中得到了一个类似的方法,避免了对Int64ToByteArray的需求,但代价是一些稍微麻烦(效率较低)的Sql,这可能不符合你的口味。
在我的源代码AdoQuery中,我有这个Sql
select *, convert(int, atimestamp) as inttimestamp from timestamps
并在目的地
select * from timestamps where convert(int, atimestamp) = :inttimestamp
当然可以避免在第二个AdoQuery上使用varBytes参数,因为可以获取timestamp列值的整数版本并将其分配给inttimestamp参数。
顺便说一下,原来的q
if ADODataset1.FieldByName('audit_timestamp').IsNull or ADODataset1.IsEmpty then
这两个表达式最好用另一种方式编写。除非ADODataset1具有持久字段,否则如果它在打开时不包含任何记录,则引用audit_timestamp应该引发"字段未找到"异常。
答案 1 :(得分:0)
似乎EMBT打破了TIMESTAMP到字节数组的转换。 bytearray的XE版本是正确的,并手动将数据作为int64下拉,然后手动构建bytearray(是否有一个开箱即用的函数?)并使用它作为参数在XE8中工作。
我不知道这是否与其他二进制数据类型有类似问题。希望不是!
工作代码:
procedure TForm2.Button1Click(Sender: TObject);
var
TestArray: TArray<Byte>;
j: integer;
function Int64ToByteArray(const inInt: uint64): TArray<Byte>;
var
i: integer;
lInt: int64;
begin
SetLength(result, 8);
lInt := inint;
for i := low(result) to high(result) do
begin
result[high(result)-i] := lInt and $FF;
lInt := lInt shr 8;
end;
end;
begin
ADODataset1.CommandText := 'SELECT *, cast(audit_timestamp as bigint) tmp FROM CURRENCYAUDIT';
ADODataset2.CommandText := 'SELECT * FROM CURRENCYAUDIT WHERE Audit_Timestamp = :Timestamp';
ADODataset2.Parameters.Refresh;
ADODataset1.Open;
if ADODataset1.FieldByName('audit_timestamp').IsNull or ADODataset1.IsEmpty then
begin
showmessage('nothing to compare');
end;
ADODataset2.Parameters[0].Value := Int64ToByteArray(ADODataset1.FieldByName('tmp').asInteger);
ADODataset2.Open;
caption := inttostr(ADODataset2.RecordCount);
end;
我还检查了这个在我的整个(真实)桌子上,并确保所有其他字段匹配,以确保它不是一次性的!
我会用EMBT提出一张票,让他们坐下来忽略5年; - )