1

I have a script, below, in Ostendo (an ERP), which runs on a firebird database. The script is written in Pascal. It returns an error "Firebird SQL: error code -104, token unknown, '13/04/2018' at the line TMPQuery2.ExecQuery. I removed the reference text DATEWORKED = {ds ''13/04/2018''} AND and it works fine. I have commented out all the other lines I tried in solving it - of which none worked.

Any ideas as to where I am going wrong? I have a feeling it is do to with date format. I have tried dd-mm-yyyy, yyyy-mm-dd (which is how it works from a OBDC through excel), dd/mm/yyyy (which is how it is displayed in ostendo).

function DuplicateTimesheetDays(ExcelFileName: String; RowCount: Integer; EmployeeName: String;): Boolean;

var
TSDateWorked, SQLStr: String;
TSBatchNo: String;
TMPQuery2     : TpFIBQuery;
ErrorMessage : String;
DuplicateDay : String;
DisplayErrorMessage : Boolean;
x: Integer;

begin

DisplayErrorMessage := False;
ErrorMessage := 'The following Days have previously been added: ' + #13#10;

LoadSpreadSheet(ExcelFileName);


for x := 1 to RowCount -1 do
   begin
            //
            //TSDateWorked := SSGetCellText(0,x);               //convert to YYYY-MM-DD
   TSDateWorked := FormatDateTime('YYYY-MM-DD',strtodate(SSGetCellText(0,x)));
   //SQLStr := 'SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE DATEWORKED = {d ''' + TSDateWorked + '''} AND EMPLOYEENAME = ''' + EmployeeName + '''';
   //SQLStr := 'SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE DATEWORKED = {ds ''2018-04-13''} AND EMPLOYEENAME = ''DE BEER''';
   SQLStr := 'SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE DATEWORKED = {ds ''13/04/2018''} AND EMPLOYEENAME = ''DE BEER''';
   //SQLStr := 'SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE EMPLOYEENAME = ''DE BEER''';
   Showmessage(SQLStr);

   try
            TMPQuery2 := TpFIBQuery.Create(nil);
            TMPQuery2.Database := OstendoDB;
            TMPQuery2.Options := qoStartTransaction + qoAutoCommit;
            TMPQuery2.SQL.clear;
            //TMPQuery2.SQL.Add('SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE DATEWORKED = {d ''' + TSDateWorked + '''} AND EMPLOYEENAME = ''' + EmployeeName + '''');
            TMPQuery2.SQL.Add(SQLStr);
   Showmessage('About to execute query');
   TMPQuery2.ExecQuery;
            if not TMPQuery2.EOF then
              begin
     TSBatchNo := TMPQuery2.FN('TIMESHEETBATCHNO').value;
              //Showmessage('Position of Batch Number in error message is: ' + pos(TSBatchNo, ErrorMessage));
              // If pos(TSBatchNo, ErrorMessage) = 0 then
        ErrorMessage := ErrorMessage + 'Duplicate Timesheet already entered on Batch No ' + TSBatchNo + ' for day ' + TSDateWorked + '.' + #13#10;
              DisplayErrorMessage := True;
              Result := True
     end;

            finally

            TMPQuery2.close;

            end;
   end; // For loop

//Display error messages if duplicates exist.
If DisplayErrorMessage then MessageDlg(ErrorMessage,mtinformation,mbok,0);

end;
3
  • What is {ds ''13/04/2018''} and why do you think it is correct? Commented Apr 17, 2018 at 11:11
  • ds stands for date stamp. There is also ts which stands for timestamp. I think it may be necessary when using a field that holds both a date and time. But it would seem this is only required when using an ODBC connection in Excel. Commented Apr 17, 2018 at 21:10
  • I'm only aware of {d ..} for date, {t ..} for time and {ts ..} for timestamp, and then only using yyyy-MM-dd for the date. And those escapes are specific for ODBC and JDBC. As far as I know, those aren't supported by Delphi, and they are definitely not supported by Firebird itself. Commented Apr 18, 2018 at 7:56

1 Answer 1

3

From where did you get the idea that date literal in Firebird is represented in format like {ds '2018-04-13'}? The legal formats to cast string data types to the DATE is listed at "Literal Formats" section in the "Conversion of Data Types" chapter.

Basically the yyyy-mm-dd format is right but it must be a simple string ie DATEWORKED = ''' + TSDateWorked + ''' when concatenating strings in pascal.

But instead of building the query as a string one should use parametrized queries. Parameters in SQL string are usually represented by name which has a colon in front of it, ie :DateWorked. So your query would look like

SQLStr := 'SELECT TIMESHEETBATCHNO FROM TIMESHEETLINES WHERE DATEWORKED = :DateWorked AND EMPLOYEENAME = :employee';
...
TMPQuery2.Params[0].AsDateTime := strtodate(SSGetCellText(0,x));
TMPQuery2.Params[1].AsString := 'DE BEER';
TMPQuery2.ExecQuery;

The query component usually also has ParamByName methods so that instead of parameter position you can assign values using the names. I don't konw the TpFIBQuery component so the property/method names might differ, consult the help of the component.

Sign up to request clarification or add additional context in comments.

1 Comment

{ds '2018-04-13'} looks like an ODBC or JDBC escape (except then it would be {d '2018-04-13'}, not ds). See ODBC reference: Date, Time, and Timestamp Literals

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.