AdoQuery无法使用SHOW:命令

时间:2011-06-05 05:16:50

标签: delphi

我正在撕扯我的头发!!

即使是像这样简单的工作:

procedure MyAdoQueryTest();
   const MYSQL_CONNECT_STRING='Driver={MySQL ODBC 5.1 Driver};Server=%s;Port=3306;Database=%s;User=%s;Password=%s;Option=3;';

   var   AdoConnection  : TADOConnection;
         ADOQuery : TADOQuery;
         Param    : TParameter;
begin
   AdoConnection := TADOConnection.Create(Nil);
   AdoConnection.ConnectionString := Format(MYSQL_CONNECT_STRING,['localhost',
                                                                  'mysql',
                                                              'root',
                                                              '']);
    AdoConnection.LoginPrompt := False;
    AdoConnection.Connected := True;

   ADOQuery := TADOQuery.Create(Nil);
   ADOQuery.Connection := AdoConnection;
   ADOQuery.Sql.Clear();
   ADOQuery.SQl.Add('SHOW :what_to_show');

   Param := ADOQuery.Parameters.ParamByName('what_to_show');
   Param.DataType := ftString;
   Param.Value := 'databases';

   ADOQuery.Prepared := true;
   ADOQuery.Active := True;
end;

(顺便说一句,我真的需要使用'Param'变量和3个语句,或者我只能'ADOQuery.Parameters.ParamByName('what_to_show')。值:='数据库';?)

无论如何,当我运行它时,我在ADOQuery.SQl.Add('SHOW :what_to_show');得到一个例外,它说“参数类型错误,超出了可接受的范围或者彼此冲突”。

我要做的是创建两个中心函数:一个将接受并执行任何不会返回任何数据的SQL语句(如INSERT INTO)和将要返回的任何数据(如SELECT)。

我目前只使用AdoConnection,但我现在正在尝试使用AdoQuery,因为我想参数化我的SQL语句来处理带引号的字符串。

我能有halpz吗?

1 个答案:

答案 0 :(得分:5)

错误在于:

ADOQuery.SQl.Add('SHOW :what_to_show');

:Param只能用于值,而不能用于动态列/关键字/表/数据库名称 这是因为如果它起作用,那么根据参数的内容,你会有SQL注入风险。

为了解决这个问题,你必须将what_to_show内容注入SQL字符串。

像这样:

var
  what_to_show: string;
begin
  ....
  what_to_show:= 'tables';
  ADOQuery.SQL.Text:= ('SHOW '+what_to_show);
  ....

现在它会起作用。

enter image description here 警告
确保测试您注入SQL的所有内容,以防止用户将SQL代码注入您的查询中 参数会阻止SQL注入,但由于您无法在此处使用它们,因此需要根据预先批准的值列表进行检查。例如a stringlist持有所有允许的what_to_shows 逃避或使用特殊字符是没用的。

安全注入示例代码

var
  what_to_show: string;
  i: integer;
  inputapproved: boolean;
begin
  ....
  what_to_show:= lower(trim(someinput));
  i:= 0;
  inputapproved:= false;
  while (i < WhiteList.count) and not(inputapproved) do begin
    inputapproved:= ( what_to_show = lower(Whitelist[i]) );
    Inc(i);
  end; {while}
  if inputapproved then ADOQuery.SQL.Text:= ('SHOW '+what_to_show);
  ....