Получение списка полей из 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;