2013-12-24 3 views
4

У меня есть две таблицы доступа: пользователи и оценки.
таблица пользователей имеет столбцы: идентификатор (автоматическое приращение идентификатор пользователя), имя пользователя, пароль - идентификатор первичного ключа таблицы результаты имеет столбцы: идентификатор (идентификатор пользователя от пользователей), рекордами - не имеет первичного ключаДоступ к базе данных INSERT с подзапросом из C#

В C# метод Я беру имя пользователя и оцениваю как параметры, и я хочу вставить в таблицу оценок, чтобы в поле id был идентификатор пользователя с именем пользователя, которое соответствует указанному.

До сих пор команды, которые я пробовал были:

string insertCommand = @"INSERT INTO scores([id], [highScore]) 
         VALUES((SELECT id FROM users WHERE username = @username), @score);"; 

Это проливает: входной запрос должен содержать, по меньшей мере, одну таблицу или запрос.

Так после обнюхивать я обнаружил, что Access БД вид отличается от обычного SQL, так что я попытался с помощью DLookup:

string insertCommand = @"INSERT INTO scores([id], [highScore]) 
         VALUES(DLookup(""id"", ""users"", ""username = '@username'""), @score);"; 

Это проходит, но в результате строка пуста. Поэтому я в основном получаю пустую строку, которая не является NULL.

Я абсолютно уверен, что параметры содержат значения, поскольку они добавляются до выполнения команды.

command.Parameters.AddWithValue("@username", username); 
command.Parameters.AddWithValue("@score", points); 

command.CommandText = insertCommand; 

command.ExecuteNonQuery(); 

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

+1

Почему не вы разбиваете его на два шага: один шаг для получения идентификатора имени пользователя, предоставленного в качестве параметра, а другой шаг - вставить в таблицу баллов. Это позволяет избежать проблемы с дополнительным запросом. – Ahmad

+0

@Ahmad Ну, я мог, но вся причина, по которой я решил использовать подзапросы, - это не делить процесс на два шага, когда это можно сделать в одном. – MrPlow

+0

Вы пробовали '' "username = @username" "' вместо '" "username = '@username'" "'? –

ответ

2

Если вы не возражаете изменения в запросе немного, следующее должно работать:

string insertCommand = @"INSERT INTO scores (id, highscore) 
         SELECT id, @highScore FROM users WHERE username = ?;"; 

Вот блок кода работает для меня в тесте:

var highScore = 99; 
var username = "johndoe"; 
OleDbConnection con = new OleDbConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString()); 

string insertCommand = @"INSERT INTO scores (id, highscore) 
         SELECT id, @highScore FROM users WHERE username = @username;"; 

OleDbCommand cmd = new OleDbCommand(insertCommand, con); 
cmd.Parameters.AddWithValue("@highScore", highScore); 
cmd.Parameters.AddWithValue("@username", username); 
con.Open(); 
cmd.ExecuteNonQuery(); 
con.Close(); 
+0

Это работает. Gotten используется для mySQL и использует 'INSERT INTO x (col1, col2, ..) VALUES (val1, val2, ..)', поэтому я никогда не думал об использовании SELECT. Так что спасибо. Одна вещь. Мне не очень нравится, как вы объединили highScore. Тем более, что вы определили его как var. Если бы какой-нибудь новичок пришел к этому, он бы не смог сделать свой код уязвимым для SQL-инъекции, используя чистую конкатенацию? – MrPlow

+0

Вы уверены? Поскольку моя команда вставки выглядит так: «string insertCommand = @» INSERT INTO (id, highscore) SELECT id, @score FROM users WHERE username = @username; ";' и работает так, как должно. – MrPlow

+0

Вы правы, это работает ... Я, должно быть, перепутал с чем-то другим. – afzalulh

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