4

我在从程序用户在运行时定义的查询中获取字段列表时遇到问题。我让我的用户将 SQL 查询输入到备忘录控件中,然后我想让他们遍历将返回的字段并执行诸如格式化输出、汇总列值等操作。所以,我必须获取列名,以便他们有一个输入附加信息的地方。

如果没有参数我会做得很好,但我也必须让他们为查询定义过滤器参数。所以,如果我想将参数设置为null,我必须知道参数的数据类型是什么。

我使用的是 Delphi 2006。我使用 DBExpress 组件 TSQLConnection 和 TSQLQuery 连接到 Firebird 2.1 数据库。以前,我成功使用:

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

当我尝试使用日期参数时,我发现我遇到了问题。直到那时我的所有参数都是整数(记录 ID)只是一个巧合。事实证明 varNull 只是一个值为 1 的枚举常量,所以我得到了可接受的结果(没有记录)工作正常。

我只需要一个字段列表。也许我应该只解析 SQL 语句的 SELECT 子句。我认为将 Qry.Prepared 设置为 True 会给我一个字段列表,但没有这样的运气。它需要参数的值。

如果你有想法,我肯定很想听听。谢谢你的帮助。

4

6 回答 6

2

尽管数据集类型略有不同,但这是我与 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;   

结尾;
你不能对查询做类似的事情吗?

于 2008-11-04T10:01:31.147 回答
2

你们这样做太难了:

for i := 0 to Qry.Params.Count - 1 do begin
    Qry.Params[i].Clear;
    Qry.Params[i].Bound := True;
end;
于 2008-11-04T13:19:17.083 回答
2

再次回复'因为我很感兴趣。我的方法有效(与我的查询一起使用),因为它们已使用参数的数据类型预定义为正确的类型:)

我不确定您如何期望查询知道或派生参数的数据类型,因为您甚至没有选择它所针对的字段。

所以我认为你的查询设置和用户输入法需要更多的关注。我刚刚查了一下我是如何做到这一点的。我不使用参数化查询——我只是从用户那里获取“参数值”并将它们直接放入 SQL 中。因此,您的 sql 将显示为:

SELECT s.hEmployee, e.sLastName
FROM PR_Paystub s
INNER JOIN PR_Employee e ON e.hKey = s.hEmployee
WHERE s.dtPaydate > '01/01/2008'

因此不需要参数类型知识。不会阻止您的用户输入垃圾,但会回到输入控制:)

于 2008-11-05T14:43:15.853 回答
1

我不确定您使用的是什么版本的 Delphi。在 Variant Types 下的 Delphi 2006 帮助中,它说:

特殊的转换规则适用于在 System 单元中声明的 Borland.Delphi.System.TDateTime 类型。当一个 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;
于 2008-11-04T01:49:52.670 回答
1

我最终做的是:

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 但这很容易。分隔符只是表示单词结尾的字符。

于 2008-11-26T20:40:23.277 回答
0
TmpQuery.ParamByName('MyDateTimeParam').DataType := ftDate;
TmpQuery.ParamByName('MyDateTimeParam').Clear;
TmpQuery.ParamByName('MyDateTimeParam').Bound := True;
于 2008-11-26T13:13:50.637 回答