我永远不应该期望知道mySQL我会使用Access安全。
我有两个表:用户和分数 users表包含:id(自动增量主键),用户名,密码等。 scoers表包含:id(number - users.id的外键),highScore
我之前已经向INSERT命令请求了帮助,现在它可以正常工作。现在我遇到类似UPDATE命令的问题。
非工作命令如下所示:
string updateCommand = @"UPDATE scores
SET
id = (SELECT id FROM users WHERE username = @username),
highScore = @score
WHERE highScore = (SELECT MIN(highScore) FROM scores);";
抛出一个:Operation must use an updateable query.
为了理顺我在这里要完成的事情:我在插入高分,直到我在表中达到10分,之后不是添加任何新分数并且不必要地填满数据库我决定它是使用UPDATE“覆盖”当前最低分数更为明智。
我提供了一个用户名和高分,因为scores
表只包含id
我需要达到当前用户的id,这就是第一个子查询正在做的事情,第二个子查询在WHERE子句中指定要替换的分数(尽管如果有多个分数最低的人可能存在错误,那么任何想法如何解决?)
我也试过像这样使用OUTER RIGHT JOIN:
string updateCommand = @"UPDATE scores
OUTER RIGHT JOIN users ON scores.id = users.id
SET
scores.id = users.id,
scores.highScore = @score
WHERE (highScore = (SELECT MIN(highScore) FROM scores)) AND (username = @username);";
没有运气(我得到通用Syntax error in UPDATE statement.
)。
浏览网页我发现我可能“不能”在UPDATE语句中使用子查询,但我似乎发现了有关此问题的相互矛盾的意见。
我也尝试使用DLookup函数代替子查询,如:
@"...
id = DLookup(""id"", ""users"", ""username = @username""),
...
WHERE highScore = DLookup(""MIN(highScore)"", ""scores"");";
elipses表示与上述代码相同的无关代码。
另外作为最后的手段,我尝试分为多个查询但是userId查询看起来像这样:
string userIdQuery = "SELECT id FROM users WHERE username = @username"
似乎返回一个空值,在我完成此操作后尝试使用变量userId时,我接收到NullReferenceException(Object reference not set to an instance of an object.
)判断:
int userId = 0;
userId = (Int32)command.ExecuteScalar();
我应该得到一个整数但是我觉得我得到一个null。获得最小高分的几乎相同的查询完美无缺,int变量用正确的值填充,所以我假设hte问题在查询本身中以某种方式。我试过在@username
参数周围添加单引号,假设它可能没有识别字符串,但似乎不是它。
答案 0 :(得分:1)
所以在经历了一些乱七八糟的事情后,我发现了我的麻烦的原因。不好的一面是我增加了代码量,以便尽可能地避免子查询,因为至少根据我的经验,Access并不真的喜欢在UPDATE
或{{1}中使用子查询命令。
我首先做的是将命令分成3个单独的命令:
INSERT
- 获取分数用户的ID
我正在加入数据库。
"SELECT id FROM users WHERE username = ?;"
- 获得id,高分
和输入时间良好的时间,当前在高分列表中的最低分数。感谢HansUp的建议,我使用了@"SELECT scores.id, scores.highScore, scores.dateTime FROM scores WHERE (((scores.highScore)=DMin(""highScore"",""scores"")));"
函数而不是使用DMin
的子查询来避免MIN
错误。无关的括号是由于Access,因为这个命令是由Access查询设计者生成的,我太害怕改变任何东西,以免打破它。
Must use an updateable query
- 更新命令本身,除了它采用先前提取的数据并将其用作命令的值之外,这里不多说。
我注意到的一件事是,即使我使命令正常工作,@"UPDATE scores SET scores.id = ?, scores.highScore = ?, scores.[dateTime] = Now() WHERE (((scores.id)=?) AND ((scores.highScore)=?) AND ((scores.dateTime)=?));"
总会返回0行受影响。在探讨之后,我发现ASP.NET / C#中命令的命名参数并不总是有效,而应该使用.ExecuteNonQuery()
代替。这有点不方便,但我不能抱怨太多。