我有以下代码,它基于许多变量构造一个SQL语句:
SQL.Add('SELECT CDbl(Answer) as An FROM v_Outcomes_FirstLastOneYear ' +
'WHERE ' + GetTool(ReportGrid.Cells[col, 0]) + ' ' +
'AND (Collector = ' + QuotedStr('Patient') + ') ' +
'AND (Question=' + GetQuestion(ReportGrid.Cells[col, 0]) + ') ' +
'AND (Answer is not null) ' +
'AND (Answer <> ''null '') ');
if Copy(ReportGrid.Cells[col, 0], Length(ReportGrid.Cells[col, 0]), 1) = '1' then
SQL.Add('AND ('+GetTPoint(first)+') ')
else
SQL.Add('AND ('+GetTPoint(second)+') ');
SQL.Add('ORDER BY CDbl(Answer)');
Run Code Online (Sandbox Code Playgroud)
ReportGrid(a TStringGrid)的第一行已经填充了一系列字符串,如'Peds phys 1',或'Peds phys 2'.最后一个数字是1或2.
变量'first'和'second'是一个进一步定义的字符串.
col是一个整数 - 此语句构造为for循环的一部分,循环遍历每个列并使用与标题对应的数据填充每一行.
GetTool(),GetQuestion()和GetTPoint()是我所定义的功能.代码GetTPoint()如下:
function GetTPoint(timepoint: string): string;
begin
if (timepoint = '0') or (timepoint = 'discharge') then
begin
if timepoint = '0' then
Result := 'FirstAxData=''TRUE'' and DischargeData=''FALSE''';
if timepoint = 'discharge' then
Result := 'DischargeData=''TRUE'' and FirstAxData=''FALSE''';
end
else
begin
timepoint := FormatFloat('0', StrToInt(timepoint)*30.4368);
Result := '[Date] BETWEEN ([Date of First CPC]+' + timepoint +
')-61 AND ([Date of First CPC]+'+timepoint+')+61';
end;
end;
Run Code Online (Sandbox Code Playgroud)
每个自定义函数都类似,只返回一个字符串.GetTool()并且GetQuestion()都工作正常但GetTPoint()抛出以下编译器错误:
E2010不兼容的类型:'string'和'procedure,无类型指针或无类型参数'
有谁知道为什么会抛出这个?
您显示的代码显示在with您正在操作的查询对象的语句中.像这样的东西:
with SomeQuery do begin
SQL.Add(...);
...
end;
Run Code Online (Sandbox Code Playgroud)
您可以SQL像这样单独引用该属性,因为该with语句将查询对象的成员带入当前范围.这意味着它的所有成员,包括First方法(用于选择第一个查询结果).在with语句范围内引入的任何内容都将隐藏在早期作用域中引入的同名内容.这包括first你说的其他地方声明的变量.
如果有表达式GetTPoint(first),编译器会将名称解释first为引用查询方法,而不是变量.该方法不是字符串,并且调用它不返回字符串,因此编译器正确地抱怨.
最好的解决方案是停止使用with.它只是为代码引入了脆弱性.如果您只是必须继续使用with,则重命名您的first变量,以便它不会干扰稍后带入范围的名称.无法引用已被另一个范围隐藏的局部变量.(如果first是全局的,你可以用单位的名称来限定它,但是应该避免全局变量和with语句一样多.)