Получение списка полей из DBExpress TSQLQuery

У меня проблема с получением списка полей из запроса, определенного во время выполнения пользователями моей программы. Я позволяю своим пользователям вводить SQL-запрос в элемент управления заметками, а затем я хочу, чтобы они проходили по полям, которые будут возвращаться, и выполняли такие действия, как форматирование вывода, суммирование значений столбца и т. д. Итак, мне нужно получить имена столбцов, чтобы у них было место для ввода дополнительной информации.

Все было бы хорошо, если бы не было параметров, но я также должен позволить им определять параметры фильтра для запроса. Итак, если я хочу установить для параметров значение null, я должен знать тип данных параметра.

Я использую Delphi 2006. Я подключаюсь к базе данных Firebird 2.1, используя компонент DBExpress TSQLConnection и TSQLQuery. Раньше я успешно использовал:

for i := 0 to Qry.Params.Count - 1 do Qry.Params[i].value := varNull;

Я обнаружил, что у меня возникла проблема, когда я попытался использовать параметр даты. Это было просто совпадение, что все мои параметры до этого были целыми числами (идентификаторами записей). Оказывается, varNull — это просто перечисляемая константа со значением 1, поэтому я получал приемлемые результаты (без записей) и работал нормально.

Мне нужен только список полей. Возможно, мне следует просто проанализировать предложение SELECT оператора SQL. Я думал, что установка Qry.Prepared в True даст мне список полей, но не повезло. Ему нужны значения для параметров.

Если у вас есть идея, я обязательно хотел бы ее услышать. Спасибо за любую помощь.


person jrodenhi    schedule 04.11.2008    source источник


Ответы (5)


Ответил еще раз, потому что мне интересно. Мои методы работают (с моими запросами), потому что они были предварительно определены с заданными типами данных params для правильного типа:)

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

Поэтому я думаю, что настройка вашего запроса и метод пользовательского ввода потребуют большего внимания. Я только что посмотрел, как я это сделал некоторое время назад. Я не использую параметризованный запрос — я просто получаю «значения параметров» от пользователя и помещаю их непосредственно в SQL. Итак, ваш sql будет читать:

ВЫБЕРИТЕ s.hEmployee, e.sLastName
ИЗ PR_Paystub s
ВНУТРЕННЕЕ СОЕДИНЕНИЕ PR_Employee e ON e.hKey = s.hEmployee
ГДЕ s.dtPaydate > '01/01/2008'

поэтому знание типа параметра не требуется. Не мешает вашим пользователям вводить мусор, но это возвращается к контролю ввода :)

person Despatcher    schedule 05.11.2008

Хотя это немного другой тип набора данных, это то, что я использую с TClientDataset, просто и эффективно :)

for i := 0 to FilterDataSet.Params.Count -1 do  
begin  
 Case FilterDataSet.Params.Items[i].Datatype of  
    ftString:  
    ftSmallint, ftInteger, ftWord:  
    ftFloat, ftCurrency, ftBCD:  
    ftDate:  
    ftTime:  
    ftDateTime:  
    .  
    .  
    . 
end;   

end;
нельзя ли сделать что-то подобное с запросом?

person Despatcher    schedule 04.11.2008

Вы, ребята, делаете это путем слишком сложным:

for i := 0 to Qry.Params.Count - 1 do begin
    Qry.Params[i].Clear;
    Qry.Params[i].Bound := True;
end;
person Craig Stuntz    schedule 04.11.2008

Я не уверен, какую версию Delphi вы используете. В справке Delphi 2006 в разделе «Типы вариантов» говорится:

Специальные правила преобразования применяются к типу Borland.Delphi.System.TDateTime, объявленному в модуле System. Когда Borland.Delphi.System.TDateTime преобразуется в любой другой тип, он обрабатывается как обычный тип Double. Когда целое, действительное или логическое значение преобразуется в Borland.Delphi.System.TDateTime, оно сначала преобразуется в Double, а затем считывается как значение даты и времени. Когда строка преобразуется в Borland.Delphi.System.TDateTime, она интерпретируется как значение даты и времени с использованием региональных настроек. Когда значение Unassigned преобразуется в Borland.Delphi.System.TDateTime, оно обрабатывается как действительное или целочисленное значение 0. Преобразование значения Null в Borland.Delphi.System.TDateTime вызывает исключение.

Последнее предложение кажется мне важным. Я бы прочитал, что, поскольку varNull не может быть преобразован в TDateTime для ввода в поле, и, следовательно, вы получаете исключение, которое вы испытываете.

Это также означает, что это единственный частный случай.

Не могли бы вы сделать что-то вроде:

for i := 0 to Qry.Params.Count - 1 do 
begin
  if VarType(Qry.Params[i].value) and varTypeMask = varDate then
  begin
    Qry.Params[i].value := Now; //or whatever you choose as your default
  end
  else
  begin
    Qry.Params[i].value := varNull;
  end;
end;
person Richard A    schedule 04.11.2008

В итоге я сделал следующее:

sNull := 'NULL';
Qry.SQL.Add(sSQL);
for i := 0 to Qry.Params.Count - 1 do begin
  sParamName := Qry.Params[i].Name;
  sSQL := SearchAndReplace (sSQL, ':' + sParamName, sNull, DELIMITERS);
end;

Мне пришлось написать SearchAndReplace, но это было легко. Разделители — это просто символы, обозначающие конец слова.

person jrodenhi    schedule 26.11.2008