【问题标题】:How to use ADO Query Parameters to specify table and field names?如何使用 ADO 查询参数指定表名和字段名?
【发布时间】:2013-10-23 16:01:30
【问题描述】:

我正在TADOQuery 中执行UPDATE 语句,并且我正在为一些事情使用参数。最初,这工作得很好,但我为表名和字段名添加了另一个参数,现在它坏了。

代码如下所示:

Q.SQL.Text:= 'update :tablename set :fieldname = :newid where :fieldname = :oldid';
Q.Parameters.ParamValues['tablename']:= TableName;
Q.Parameters.ParamValues['fieldname']:= FieldName;
Q.Parameters.ParamValues['oldid']:= OldID;
Q.Parameters.ParamValues['newid']:= NewID;

我得到的错误:

我假设这是因为我使用了这个字段名两次。我可以通过第二次使用另一个唯一字段名称来克服这个问题,但是我仍然遇到另一个错误:

如何使用参数指定要更新的表和字段?

【问题讨论】:

  • IIRC,如果您重用这样的参数名称,则必须遍历所有参数才能找到它的所有实例。也就是说,我不确定您是否可以将参数用于表名或字段名。您可能需要为值执行带参数的动态 SQL。

标签: sql delphi parameters ado


【解决方案1】:

查询参数并非旨在参数化表名。

您可以做的是在 SQL 中为表名使用占位符,然后使用 Format 函数将这些占位符替换为表名,然后使用其他值的参数像往常一样。这对于 SQL 注入来说仍然是相对安全的(恶意的人必须知道准确的表名、正在使用的特定 SQL 语句以及为参数提供的值)。

const
  QryText = 'update %s set :fieldname = :newid where :fieldname = :oldid';
begin
  Q.SQL.Text := Format(QryText, [TableName]);
  Q.Parameters.ParamValues['fieldname'] := FieldName;
  Q.Parameters.ParamValues['oldid'] := OldID;
  Q.Parameters.ParamValues['newid'] := NewID;    
  ...
end;

【讨论】:

  • 对数据库具有只读访问权限(例如,用于报告)的人会知道表和列的名称以及值,因此不会安全注入。只要程序可以为 TableName 和 ColumnName 提供值(从不接受用户输入),IT 将是安全的
  • @GerryColl:请再读一遍我说的话。我说的是“相对安全”,而不是“安全”。为了在此处注入 SQL,您不仅需要知道确切的表名和列名,还需要知道用于被攻击的特定 INSERT 或 UPDATE 的 SQL 语句的实际文本。它与 SQL 连接的风险不同。 (并且具有“只读访问权限”的人不会有风险,因为他们具有“只读访问权限”,对吗?他们将无法执行 UPDATE 或 INSERT,因为他们已“阅读- 仅访问”。)
  • 实际上,我确实设法通过参数获取了引用的列名。但是,表名是导致问题的原因。在这种情况下,您的开场陈述会更有意义,说“查询参数并非旨在参数化表名。”
  • @JerryDodge:好的。 :-) 进行了相应的编辑。
  • 该编辑仍然存在相同参数被使用两次的原始问题 :-) 但是,出于这个原因,我仍然喜欢使用 Format 函数的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
相关资源
最近更新 更多