SQL没有找到结果
Posted
技术标签:
【中文标题】SQL没有找到结果【英文标题】:SQL not finding results 【发布时间】: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 < 1 then Result := 0
它给我结果 0
这看起来不像“字段是 NEED_2_TARGET、ID 和 CARD”,以及您对 Gordon 的回复(他说“比较 值 时访问区分大小写”)是“数据库中的所有字段都是大写” - “Ash Imp”对我来说似乎不是全部大写。话虽如此,根据您提供的信息,我认为您的查询没有任何问题(假设现在是准确的)。
@GordonLinoff re:“比较值时访问区分大小写” - 不,不是。看here。
【参考方案1】:
有很多事情可能会出错。
在您的故障排除中,首先也是最重要的是获取您的查询并直接针对您的数据库运行它。 IE。首先通过消除其他事情出错的可能性来确认您的查询是正确的。确认工作的事情越多,分散您解决问题的“噪音”就越少。
-
正如其他人所指出的,如果您不清除 SQL 语句,您可能会在 first 结果集中返回零行。
是的,我知道,您已经评论说您正在清除您之前的查询。关键是:如果您在解决问题时遇到困难,您如何确定问题出在哪里?所以,不要遗漏可能相关的信息!
这巧妙地将我们带到了第二种可能性。我看不到您的其余代码,所以我不得不问:您是否在更改查询后刷新数据?如果您没有
Close
和Open
您的查询,您可能正在查看先前执行的结果集。
我不确定您是否可以在组件为Active
时更改查询文本,或者甚至不确定这是否取决于您正在使用的数据访问组件。关键是,值得检查。
您的应用程序是否连接到正确的数据库?由于您使用的是 Access,因此很容易在没有意识到的情况下连接到不同的数据库文件。
您可以通过更改查询以返回所有行来检查这一点(即删除 WHERE 子句)。
您希望更改 SQL 查询中使用的引号。而不是:...CARD = "'+name+'" ORDER...
而不是使用...CARD = '''+name+''' ORDER...
据我所知,单引号是 ANSI 标准。即使某些数据库允许双引号,但使用它们会限制可移植性,并且在通过某些数据访问驱动程序传递时可能会产生意外结果。
检查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 总是可以很容易地更改为局部变量别名,因此绝对没有必要让自己承担风险。以上是关于SQL没有找到结果的主要内容,如果未能解决你的问题,请参考以下文章