Представление Firebird/Lazarus SQL с выбором iif?

Я хочу выбрать строки из таблицы с вычисляемым полем, определенным с помощью запроса выбора.

Например, мой выбор может быть:

Select FirstName, 
       LastName, 
       iif(Cast('Now' as date)-BirthDate<18, 'Minor', 'Major') as StatAge 
from TableUsers;

С Lazarus я хочу фильтровать StatAge.

Я попробовал свой запрос непосредственно в моей базе данных с помощью инструмента.

Я могу фильтровать с помощью Where в моем запросе следующим образом:

Select * 
from (
  Select FirstName, 
         LastName, 
         iif(Cast('Now' as date)-BirthDate<18, 'Minor', 'Major') as StatAge 
  from TableUsers
) 
Where StatAge = 'Minor';

Но это не работает на lazarus с TSQLQuery.Filter. Я могу фильтровать по другим полям и без проблем. Моя проблема только с этим вычисляемым полем.

Так что, может быть, мне нужно создать представление в моей базе данных? Но у меня есть ошибка, когда я пытался добавить свое представление с моим запросом.

Мой код SQL для создания представления приведен ниже, и ошибка

«Неудачное обновление метаданных не может отформатировать сообщение 8:132 — файл сообщения C:\WINDOWS\SYSTEM32\firebird.msg не найден.

Я никогда не видел, что в прошлом:

CREATE VIEW "TSTT_SELECT" ("ID_SENT", "Eng", "Char", "ID_STT", "Order", "Stat", "StartSAE", "RetSAE", "ArrSAE", "StartSHE", "RetSAE") 
AS 
Select "EMAIL_SENT"."ID", "EMAIL_SENT"."COMMANDE_TABLE", "EMAIL_SENT"."CHAR", "TSTT"."ID", "TSTT"."ORDER", iif("TSTT"."RETOUR_PREV" Is Not Null AND ("TSTT"."RETOUR_PREV">cast('Now' as date)), 'En retard', iif("TSTT"."Depart_SAE" Is Null, 'A expedier', iif("TSTT"."Depart_SAE" Is Not Null And "TSTT"."Arrivee_SHE" Is Not Null And "TSTT"."Depart_SHE" is null,'Chez le STT',iif("TSTT"."Depart_SHE" Is Not Null, 'Au depart STT', iif("TSTT"."Arrivee_SAE" Is Not Null, 'Récéptionné', ''))))) as "Statut", "TSTT"."Depart_SAE", "TSTT"."RETOUR_PREV", "TSTT"."Arrivee_SHE", "TSTT"."Depart_SHE", "TSTT"."Arrivee_SAE" 
from "EMAIL_SENT" 
   Left join "TSTT" on "EMAIL_SENT"."ID" = "TSTT"."ID_EMAIL";

person Mathieu    schedule 15.02.2019    source источник
comment
здесь вы смешиваете две разные проблемы: использование TSQLQuery.Filter в FPC/Lazarus и создание представлений в Firebird. Это разные проблемы и про разные программы. В.р.т. Firebird - похоже, вы не установили клиент Firebird в системе. Таким образом, рядом с fbclient.dll нет файла firebird.msg, поэтому он не может предоставить вам текст ошибки. Найдите файл msg последней версии Firebird и поместите его рядом с клиентской dll, которую использует ваша программа. P.S. также может быть лучше использовать CURRENT_DATE var, firebirdsql.org/refdocs/langrefupd25-now.html< /а>   -  person Arioch 'The    schedule 15.02.2019
comment
Ошибка выглядит как код 336068740, который является таблицей ... уже существует. Это говорит о том, что у вас уже есть представление (или таблица) с именем TSTT_SELECT.   -  person Mark Rotteveel    schedule 15.02.2019
comment
@MarkRotteveel откуда ты знаешь код? grepped источники FB для 8:132 ?   -  person Arioch 'The    schedule 15.02.2019
comment
@Arioch'Коды ошибок - 0x14000000 | (facility << 16) | (number & 0xFFFF), здесь объект - 8, а номер - 132. Хотя я мог бы также искать в src/msgs/message2.sql на 8, 132.   -  person Mark Rotteveel    schedule 16.02.2019


Ответы (2)


Предполагая, что ваше поле BirthDate имеет тип Date, если вы используете такую ​​утилиту, как FlameRobin, для выполнения сначала SQL, который вы цитируете в своем q, а затем следующего SQL, вы увидите, что в вашем SQL есть ошибка. Ошибка заключается в том, что ваш iff возвращает количество дней, а не лет, поэтому возвращаемое значение iff неверно. Я не очень хорошо знаком с Firebird SQL, поэтому в моей версии я "исправил" это, умножив 18 на 365, что, конечно, игнорирует високосные годы.

Select FirstName,
       LastName,
       Birthdate,
       iif(Cast('Now' as date)-BirthDate<18 * 365, 'Minor', 'Major') as StatAge ,
       Cast('Now' as date)-BirthDate
from TableUsers;

Затем я установил минимальный проект Lazarus, описанный ниже, и он отлично работает, включая правильную фильтрацию выражения edFilter.Text.

Код:

  TForm1 = class(TForm)
    Button1: TButton;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    edFilter: TEdit;
    SQLConnector1: TSQLConnector;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  public
  end;

  [...]

  procedure TForm1.Button1Click(Sender: TObject);
  begin
    if not SQLQuery1.Filtered then
      SQLQuery1.Filter := edFilter.Text
    else
      SQLQuery1.Filter := '';
    SQLQuery1.Filtered := not SQLQuery1.Filtered;
  end;

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    edFilter.Text := 'STATAGE = ''Minor''';
    SQLQuery1.Sql.Text :=
    'Select '#13#10
    + '  FirstName, '#13#10
    + '  LastName, '#13#10
    + '  Birthdate, '#13#10
    + '  iif(Cast(''Now'' as date)-BirthDate<18 * 365, ''Minor'', ''Major'') as StatAge , '#13#10
    + '  Cast(''Now'' as date)-BirthDate '#13#10
    + 'from TableUsers2;';

    SqlQuery1.Open;
  end;
person MartynA    schedule 15.02.2019
comment
Помогло ли это решить вашу проблему с фильтрацией? - person MartynA; 20.02.2019

Итак, я решил свою проблему с компонентом IBX4Lazarus. Это специальный компонент для Interbase/firebird.

Я использовал его в прошлом, потому что lazarus не интегрировал firebird. Теперь мы можем подключиться к БД firebird со стандартным компонентом Lazarus, но мы видим, что есть некоторые проблемы... Поэтому я буду работать только с компонентами IBX для лучшей оптимизации.

Моя проблема решена с помощью IBX4Lazarus: www.mwasoftware.co.uk

person Mathieu    schedule 15.02.2019
comment
Хм. Я не уверен, что верю, что ваша проблема решена. Я нашел ошибку в вашем вопросе, что означает, что он не может работать правильно, если мои предположения верны. У меня есть минимальный проект, написанный в Delphi, который отлично работает (включая фильтрацию). Я попытаюсь переписать его для Lazarus и опубликовать как новый ответ в течение следующего часа или около того, если он сработает. - person MartynA; 15.02.2019