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

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

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

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

для i:= 0 для Qry.Params.Count - 1 do Qry.Params[i].value:= varNull;

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

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

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

6 ответов

Решение

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

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

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

ВЫБЕРИТЕ s.hEmployee, e.sLastName
FROM PR_Paystub s
INNER JOIN PR_Employee e ON e.hKey = s.hEmployee
ГДЕ s.dtPaydate > '01/01/2008'

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

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

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

Хотя немного другой тип набора данных, это то, что я использую с 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;   

конец;
Вы не можете сделать что-то подобное с запросом?

То, что я закончил, было этим:

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, но это было легко. Разделители - это просто символы, обозначающие конец слова.

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

Специальные правила преобразования применяются к типу Borland.Delphi.System.TDateTime, объявленному в системном блоке. Когда Borland.Delphi.System.TDateTime преобразуется в любой другой тип, он обрабатывается как обычный Double. Когда целое, вещественное или логическое значение преобразуется в Borland.Delphi.System.TDateTime, оно сначала преобразуется в Double, а затем считывается как значение даты и времени. Когда строка преобразуется в Borland.Delphi.System.TDateTime, она интерпретируется как значение даты и времени с использованием региональных настроек. Когда неназначенное значение преобразуется в Borland.Delphi.System.TDateTime, оно обрабатывается как действительное или целочисленное значение 0. Преобразование пустого значения в 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;
TmpQuery.ParamByName('MyDateTimeParam').DataType := ftDate;
TmpQuery.ParamByName('MyDateTimeParam').Clear;
TmpQuery.ParamByName('MyDateTimeParam').Bound := True;
Другие вопросы по тегам