我遇到快速报告显示ADOquery中的错误数据的问题。我使用以下sql.text
SELECT * FROM JOB_DATA
INNER JOIN CUSTOMER ON JOB_DATA.CUST_CODE = CUSTOMER.CUST_CODE
WHERE JOB_DATA.SHIP_DATE Between [Date1] And [Date2]
ORDER by SHIP_DATE
快速报告仅显示SHIP_DATE = null的数据。
如果我抛出一个TDBgrid并将其附加到连接到同一ADOquery的数据源,那么dbgrid会显示正确的信息。
我没有想法,有什么建议吗?
回答有关日期来源的问题:
var
date1:string;
date2:string;
sql_str:string;
begin
date1:=inputbox('Date Range','Enter Beginning Date','');
Try
StrToDate(date1);
Except
On EConvertError Do
Begin
MessageDlg('Please enter a valid date. Format xx/xx/xx',
mtError, [mbOK], 0);
//ShowMessage('Please enter a valid date. Format `enter code here`xx/xx/xx');
Exit;
End;
End;
date2:=inputbox('Date Range','Enter Ending Date','');
Try
StrToDate(date2);
Except
On EConvertError Do
Begin
MessageDlg('Please enter a valid date. Format xx/xx/xx',
mtError, [mbOK], 0);
//ShowMessage('Please enter a valid date. Format `enter code here`xx/xx/xx');
Exit;
End;
End;
sql_str:= 'SELECT * FROM JOB_DATA INNER JOIN CUSTOMER ON ' +
'JOB_DATA.CUST_CODE = CUSTOMER.CUST_CODE ' +
'WHERE JOB_DATA.SHIP_DATE Between ';
sql_str:= sql_str+ ''' ';
sql_st:=sql_str + date1;
sql_str:= sql_str+ '''';
sql_str:= sql_str+ ' AND ';
sql_str:= sql_str+ ''' ';
sql_str:= sql_str+ date2;
sql_str:= sql_str+ ' ''';
with ADOQuery5 do
begin
Close;
SQL.Clear;
SQL.text:= sql_str;
Open;
end;
frxreport2.ShowReport();
end;
ADOquery附加到附加到frxReport2的frxDBDataset2。我没有采取任何措施来改变查询中的结果。
不,我在报告中没有代码,它全部是从向导生成的。
答案 0 :(得分:2)
FastReport无法仅在SHIP_DATE
为NULL
的情况下显示记录,因为如果WHERE
和Date1
您的查询不应根据Date2
子句返回它们正确分配。这意味着您的数据集和FastReport没有正确连接,或者您的代码中的某些内容为BETWEEN
子句指定日期值是错误的,并且日期未正确提供给查询。
开始查看的第一个地方是确保为所有报告列正确分配了正确的TfrxDataSet
和正确的数据库列。 (单击报表项(文本对象或其可能的任何对象),并检查其DataSet
和DataField
属性以确保它们正确。)
如果这不是问题,则可能是您构建查询的方式,这可能无法正确格式化ADO的日期。 (您只是使用任何格式来传递StrToDate
调用而不会引发异常。)
您设置SQL的方式实际上是无法控制的。当您尝试在代码中管理自己的引用时,它是不可读的和不可维护的。
您应该使用参数,这些参数首先保护您免受SQL注入,但也允许数据库驱动程序为您正确格式化引用的值和日期,并保持可读性。 (你也可以使用可读的名字作为参数,这样当你看到他们六个月之后你会知道他们的意思。)
var
// Your other variable declarations here
StartDate, EndDate: TDateTime;
begin
Date1 := InputBox(Whatever);
try
StartDate := StrToDate(Date1);
except
// Handle EConvertError
end;
Date2 := InputBox(Whatever);
try
EndDate := StrToDate(Date2);
except
// Handle EConvertError
end;
sql_str := 'SELECT * FROM JOB_DATA J'#13 +
'INNER JOIN CUSTOMER C'#13 +
'ON J.CUST_CODE = C.CUST_CODE'#13 +
'WHERE J.SHIP_DATE BETWEEN :StartDate AND :EndDate';
with ADOQuery5 do
begin
Close;
// No need to clear. If you're using the same query more than once,
// move the SQL assignment and the Parameter.DataType somewhere
// else, and don't set them here.
// The query can be reused just by closing, changing parameter values,
// and reopening.
SQL.Text := sql_str;
with Parameters.ParamByName('StartDate') do
begin
DataType := ftDate;
Value := StartDate;
end;
with Parameters.ParamByName('EndDate') do
begin
DataType := ftDate;
Value := EndDate;
end;
Open;
end;
frxReport2.ShowReport;
end;
答案 1 :(得分:0)
当我开始遇到ADO问题时,我会记录信息。
你需要创建自己的记录器......但这里是它的开玩笑...注意它会记录传递给查询的参数值,包括SQL。
procedure TLogger.SetUpConnectionLogging(aParent: TComponent);
var
a_Index: integer;
begin
for a_Index := 0 to aParent.ComponentCount - 1 do
if aParent.Components[a_Index] is TAdoConnection then
begin
TAdoConnection(aParent.Components[a_Index]).OnWillExecute := WillExecute;
TAdoConnection(aParent.Components[a_Index]).OnExecuteComplete := ExecuteComplete;
end;
end;
procedure TLogger.ExecuteComplete(Connection: TADOConnection;
RecordsAffected: Integer; const Error: Error; var EventStatus: TEventStatus;
const Command: _Command; const Recordset: _Recordset);
var
a_Index: integer;
begin
AddLog('AdoConnection ExecuteComplete', True);
AddLog('Execution In MilliSeconds', IntToStr(MilliSecondsBetween(Time, FDif)));
AddLog('Execution In Seconds', IntToStr(SecondsBetween (Time, FDif)));
AddLog('Execution In Minutes', IntToStr(MinutesBetween (Time, FDif)));
AddLog('CommandText', Command.CommandText);
if Assigned(Command) then
begin
AddLog('Param Count', IntToStr(Command.Parameters.Count));
for a_Index := 0 to Command.Parameters.Count - 1 do
begin
AddLog(Command.Parameters.Item[a_Index].Name, VarToWideStr(Command.Parameters.Item[a_Index].Value));
end;
AddLog('CommandType', GetEnumName(TypeInfo(TCommandType),Integer(Command.CommandType)));
end;
AddLog('EventStatus', GetEnumName(TypeInfo(TEventStatus),Integer(EventStatus)));
if Assigned(RecordSet) then
begin
AddLog('CursorType', GetEnumName(TypeInfo(TCursorType),Integer(Recordset.CursorType)));
AddLog('LockType', GetEnumName(TypeInfo(TADOLockType),Integer(Recordset.LockType)));
end;
AddLog('RecordsAffected', IntToStr(RecordsAffected));
AddLog('AdoConnection ExecuteComplete', False);
end;
procedure TLogger.WillExecute(Connection: TADOConnection;
var CommandText: WideString; var CursorType: TCursorType;
var LockType: TADOLockType; var CommandType: TCommandType;
var ExecuteOptions: TExecuteOptions; var EventStatus: TEventStatus;
const Command: _Command; const Recordset: _Recordset);
begin
AddLog('Connection WillExecute', True);
AddLog('Connection Name', Connection.Name);
AddLog('CommandText', CommandText);
AddLog('CommandType', GetEnumName(TypeInfo(TCommandType),Integer(CommandType)));
AddLog('EventStatus', GetEnumName(TypeInfo(TEventStatus),Integer(EventStatus)));
AddLog('CursorType', GetEnumName(TypeInfo(TCursorType),Integer(CursorType)));
AddLog('Connection WillExecute', False);
FDif := Time;
end;