2013-12-25 2 views
0

Я никогда не ожидал, что, зная mySQL, я буду в безопасности с использованием Access.Доступ к базе данных UPDATE с подзапросом

У меня есть две таблицы: пользователи и оценки пользователи таблица содержит: идентификатор (автоматическое приращение первичного ключа), имя пользователя, пароль и т.д .. scoers таблица содержит ID (номер - внешний ключ users.id), рекордами

Я ранее обращался за помощью к команде 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.

рационализировать то, что я пытаюсь достичь здесь: Я ВСТАВИТЬ-не ИНГА высоких баллов до I довести до 10 баллов в таблице, а затем вместо добавления каких-либо новых баллов и заполнения базы данных без необходимости. Я решил, что было бы разумнее просто «перезаписать» самый низкий балл, используя UPDATE.

Я поставила имя и высокий балл и поскольку scores таблица содержит только id Мне нужно, чтобы достичь идентификатора текущего пользователя, так это то, что первый подзапрос делает, второй подзапрос в ИНЕКЕ должен указать который забьет заменить (хотя есть, возможно, ошибка здесь, если есть несколько людей с самой низкой оценкой, какие-либо идеи, как исправить это?)

Я также попытался использовать OUTER JOIN RIGHT, как это:

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" 

кажется возвращает нулевой судя по NullReferenceException я получаю (Object reference not set to an instance of an object.) при попытке использовать переменная идентификатор пользователя после того, как я сделал это:

int userId = 0; 
userId = (Int32)command.ExecuteScalar(); 

Я должен получить целое число, однако я получаю нуль я думаю. Почти идентичный запрос для получения минимального рекорда работает безупречно, а переменная int заполняется правильным значением, поэтому я предполагаю, что проблема hte в самом запросе. Я попытался добавить одинарные кавычки вокруг параметра @username, предполагая, что он может не распознавать строку, но кажется, что это не так.

Пху .. взял меня на то, чтобы написать это. У кого-нибудь есть идеи о том, как заставить все это работать? Если вам нужна дополнительная информация, дайте мне знать.

+0

@HansUp Я попытался создать его в доступе и получил команду, которая выполняет внутреннее соединение, и все, что ему кажется в доступе, - это выбрать запись с наименьшим идентификатором, не изменяя при этом ничего. Команда выглядит так: 'UPDATE users INNER JOIN scores ON users.id = scores.id SET scores.id = (SELECT [users]. [Id] FROM [users] WHERE [users]. [Username] =" Member "), scores.highScore = 1234 WHERE (((scores.highScore) = (SELECT Min ([score]. [highScore]) FROM [score])));' – MrPlow

+0

@HansUp Я ушел, потому что у меня было некоторые поручения, чтобы бежать, поэтому я должен был уйти на некоторое время. Я не совсем понимаю ваше предложение. Вы имеете в виду, что в подзапросе я должен каким-то образом извлечь строку баллов, которую я обновляю? Или что я должен как-то сделать это заранее (извлечь его в переменные, а затем обновить значения?). Если это последний, то я не вижу смысла использовать для выбора имени пользователя, так как я только хочу изменить оценку и идентификатор пользователя, который он связывает с – MrPlow

+0

@HansUp Также, пытаясь использовать команду во втором комментарии, я получаю ошибку 'Must use updateable query', в то время как я не могу заставить DMin работать в доступе напрямую, а тем более через ASP.NET. В критериях я пробовал '= DMin ('highScore', 'score')', '= DMin ([score]. [HighScore], [score])', '= DMin (" [score]. [HighScore] "," [score] ")' не повезло, я продолжаю получать 'Введенное выражение содержит недопустимый синтаксис. 'ошибка. – MrPlow

ответ

1

Итак, после некоторого возиться, я выяснил причины моих проблем. Плохая сторона заключается в том, что я увеличил количество кода, чтобы избежать как можно большего количества подзапросов, поскольку, по крайней мере, из моего опыта, Access не очень нравится использование подзапросов в командах UPDATE или INSERT.

То, что я сделал первый расщепляется команду на 3 отдельных из них:

  • "SELECT id FROM users WHERE username = ?;" - Для того, чтобы получить идентификатор пользователя, чей счет я помещаю в базе данных.

  • @"SELECT scores.id, scores.highScore, scores.dateTime FROM scores WHERE (((scores.highScore)=DMin(""highScore"",""scores"")));" - который получает идентификатор, высокий балл и время, когда запись была ... хорошо введена, самой низкой оценки в настоящее время в списке лучших результатов. Благодаря предложению от HansUp я использовал функцию DMin вместо подзапроса с MIN, чтобы избежать ошибки Must use an updateable query. Посторонние круглые скобки связаны с Access, поскольку эта команда была создана конструктором запросов Access, и я слишком боюсь изменить что-либо, чтобы я не сломал его.

  • @"UPDATE scores SET scores.id = ?, scores.highScore = ?, scores.[dateTime] = Now() WHERE (((scores.id)=?) AND ((scores.highScore)=?) AND ((scores.dateTime)=?));" - Сама команда обновления, не так много сказать, кроме того, что она берет ранее извлеченные данные и использует ее в качестве значений для команды.

Одна вещь, которую я заметил, что даже если бы я получил команду работать .ExecuteNonQuery() всегда будет возвращать 0 строк пострадавших. После того, как я выскочил, я обнаружил, что именованные параметры для команд в ASP.NET/C# не всегда работают, и вместо этого следует использовать ?. Это немного неудобно, но я не могу жаловаться слишком много.

Смежные вопросы