【问题标题】:SQL not finding resultsSQL没有找到结果
【发布时间】:2014-01-26 01:02:00
【问题描述】:

此查询当前没有返回任何结果,它应该返回。你能看出这个查询有什么问题吗

字段标题为 NEED_2_TARGET、ID 和 CARD

NEED_2_TARGET = 整数

卡片 = 字符串

ID = 整数

名字的值是'Ash Imp'

{this will check if a second target is needed}
//**************************************************************************
function TFGame.checkIf2ndTargetIsNeeded(name: string):integer;
//**************************************************************************
var
  targetType : integer; //1 is TCard , 2 is TMana , 0 is no second target needed.
begin
    TargetType := 0;
    Result := targetType;
       with adoquery2 do
        begin
          close;
          sql.Clear;
          sql.Add('SELECT * FROM Spells WHERE CARD = '''+name+''' and NEED_2_TARGET = 1');
          open;
        end;

        if adoquery2.RecordCount < 1 then
          Result := 0
       else
         begin
           Adoquery2.First;
           TargetType := adoquery2.FieldByName(FIELD_TARGET_TYPE).AsInteger;
           result := TargetType;
         end;

end;

sql db 如下所示

ID  CARD    TRIGGER_NUMBER  CATEGORY_NUMBER QUANTITY    TARGET_NUMBER   TYPE_NUMBER PLUS_NUMBER PERCENT STAT_TARGET_NUMBER  REPLACEMENT_CARD_NUMBER MAX_RANDOM  LIFE_TO_ADD REPLACED_DAMAGE NEED_2_TARGET   TYPE_OF_TARGET
27  Ash Imp     2                   2          15             14                                                                                                                                  1             1

【问题讨论】:

  • 显示你的数据来证明你的假设。
  • 请编辑您的问题以提供应该匹配但不匹配的数据。此外,如果您使用参数化查询,它们的执行速度会更快(它们只编译一次),并且您可以消除所有 "'+name+'" 垃圾。您也不应该在没有SQL.Clear 的情况下首先使用SQL.Add,如果您使用的是单个语句,则可以使用SQL.Text 将整个SQL 语句替换为一行代码。 Add 附加到现有 SQL 的末尾,这意味着您可能没有按照您的想法执行。
  • 我知道它没有返回任何结果,因为我跟踪扔了它,当我到达 if adoquery2.RecordCount &lt; 1 then Result := 0 它给我结果 0
  • 这看起来不像“字段是 NEED_2_TARGET、ID 和 CARD”,以及您对 Gordon 的回复(他说“比较 值 时访问区分大小写”)是“数据库中的所有字段都是大写” - “Ash Imp”对我来说似乎不是全部大写。话虽如此,根据您提供的信息,我认为您的查询没有任何问题(假设现在是准确的)。
  • @GordonLinoff re:“比较值时访问区分大小写” - 不,不是。看here。

标签: sql delphi ms-access


【解决方案1】:

有很多事情可能会出错。

在您的故障排除中,首先也是最重要的是获取您的查询并直接针对您的数据库运行它。 IE。首先通过消除其他事情出错的可能性来确认您的查询是正确的。确认工作的事情越多,分散您解决问题的“噪音”就越少。

  1. 正如其他人所指出的,如果您不清除 SQL 语句,您可能会在 first 结果集中返回零行。
    • 是的,我知道,您已经评论说您正在清除您之前的查询。关键是:如果您在解决问题时遇到困难,您如何确定问题出在哪里?所以,不要遗漏可能相关的信息!
  2. 这巧妙地将我们带到了第二种可能性。我看不到您的其余代码,所以我不得不问:您是否在更改查询后刷新数据?如果您没有Close 和Open 您的查询,您可能正在查看先前执行的结果集。
    • 我不确定您是否可以在组件为Active 时更改查询文本,或者甚至不确定这是否取决于您正在使用的数据访问组件。关键是,值得检查。
  3. 您的应用程序是否连接到正确的数据库?由于您使用的是 Access,因此很容易在没有意识到的情况下连接到不同的数据库文件。
    • 您可以通过更改查询以返回所有行来检查这一点(即删除 WHERE 子句)。
  4. 您希望更改 SQL 查询中使用的引号。而不是:...CARD = "'+name+'" ORDER... 而不是使用...CARD = '''+name+''' ORDER...
    • 据我所知,单引号是 ANSI 标准。即使某些数据库允许双引号,但使用它们会限制可移植性,并且在通过某些数据访问驱动程序传递时可能会产生意外结果。
  5. 检查CARD 列的数据类型。如果它是一个固定长度的字符串,那么数据值将被填充。例如。如果CARD 是char(10),那么您实际上可能需要寻找'Ash Imp '。
    • 同样,实际值可能在单词之前/之后包含空格。使用不带 WHERE 的 select 并检查列的实际值。您还可以检查SELECT * FROM Spells WHERE CARD LIKE '%Ash Imp%' 是否有效。

最后,正如其他人所建议的,您最好使用参数化查询,而不是自己动态构建查询。

  • 您的代码将更具可读性和灵活性。
  • 你可以让你的代码强类型;因此避免将数字和日期等内容转换为字符串。
  • 您无需担心日期格式的特殊性。
  • 您消除了一些安全问题。

【讨论】:

  • 好的,我已经尝试使用 ' 并且仍然没有好处.. 但如果我使用 sql.Add('SELECT * FROM Spells'); 它确实会找到记录。是的,我有Close sql.clear sql.add Open 还有其他建议吗?
  • @GlenMorse 我添加了一个我第一次忘记包含的选项。另外,您是否直接在数据库上运行查询以确认没有其他问题。使用SELECT * FROM Spells 是一种类似的消除技术,但并不完全相同。因此,直接在数据库上运行您的预期查询仍然很重要。
【解决方案2】:

@GordonLinoff db 中的所有字段都是大写

如果这是真的,那是你的问题。 SQL 通常对字符/字符串值进行区分大小写的比较,除非您告诉它不要这样做,例如 STRCMP() (MySQL 4+)、LOWER() 或 UPPER() (SQLServer、Firebird) 等。我也会尽可能将条件括在括号中:

sql.Text := 'SELECT * FROM Spells WHERE (NEED_2_TARGET = 1) AND (STRCMP(CARD, "'+name+'") = 0) ORDER by ID';

sql.Text := 'SELECT * FROM Spells WHERE (NEED_2_TARGET = 1) AND (LOWER(CARD) = "'+LowerCase(name)+'") ORDER by ID';

sql.Text := 'SELECT * FROM Spells WHERE (NEED_2_TARGET = 1) AND (UPPER(CARD) = "'+UpperCase(name)+'") ORDER by ID';

【讨论】:

  • 除非那不是真的,根据他发布的数据和name中的值。 name 和列的内容都不是大写的。
  • 我确实说过“如果那是真的”:)
  • 我知道。我没有投反对票。 :-) 只是指出张贴者已经在这里对事实进行了几次失实陈述,包括发布的数据清楚地表明事实并非如此。
  • @GlenMorse:“Ash Imp”,卡片栏。 (Gordon 引用了“比较值”,意思是“匹配内容”,您回答“db 中的所有字段都是大写”。
  • cc: @CraigYoung - 当 Gordon Linoff 说“比较值时访问区分大小写”时,他是不正确的。看here。
【解决方案3】:

这是或曾经是一个问题

With Adoquery2 do
begin
...
end

在 sql 中使用 name 时,实际上得到的是 adoquery2.name 而不是 var 名称。我通过将name 更改为Cname 解决了这个问题,之后就没有问题了。

【讨论】:

  • 而 with 又来了!使用 eval 工具提示而不是 Name,您无法轻易注意到问题,这使情况变得更糟 - 因为那不起作用! @GlenMorse 您刚刚从 with 声明中遭受了第一口。我强烈建议您宁愿完全消除 with,否则您将来可能会遇到更多糟糕的体验。关键是 with 总是可以很容易地更改为局部变量别名,因此绝对没有必要让自己承担风险。
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
相关资源
最近更新 更多