Как говорится в прошлом, вы не можете передать столбец name в SQL-запрос OleDB в качестве параметра. Параметры только для значений, а не имен таблиц или столбцов.
Как упоминают в своих комментариях неудачные пройденные попытки, это небезопасно - так как это может быть опасно. Основная проблема заключается в том, что если имя таблицы получено из пользовательского ввода - если это так, это оставит уязвимость SQL-инъекции в вашем приложении. Таким образом, если это действительно происходит из-за пользовательского ввода, вам нужно защитить себя. Самый простой способ — убедиться, что имя таблицы является допустимой таблицей, прикрепленной таблицей или именем запроса. Для этого вы можете использовать такой запрос:
SELECT Name FROM Myssobjects Where Type in (1,5,6,)
Этот запрос вернет вам действительные значения для таблиц в вашей базе данных, которые вы сможете сравнить с полученными вами входными данными. Обратите внимание, что вы все равно должны использовать это с осторожностью, потому что в большинстве случаев вы не захотите, чтобы ваш пользователь имел доступ ко всей вашей базе данных.
В любом случае, если вы хорошо защитили себя и убедились, что больше не уязвимы, способ сделать это — динамически создать строку для запроса, например:
string tableName = value;
string query = "INSERT INTO t1 select "+tableName+",c2 FROM t2 WHERE c3= $v2";
SqlCommand cmd= new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("$v2", data);
// etc. - instead of the AddWithValue(), you add it to the string.
EDIT: поскольку это не совсем то, о чем вы просили, я объясню, что я имею в виду в отношении вашего псевдокода:
$insertv1=$v1
$insertv2= select c2 from t2 where c3=$v2
query = insert INTO t1 VALUES ($insertv1,$insertv2)
На самом деле потребуется разделить два запроса и, таким образом, перевести на:
string v1="Your value here.",v2="Your second value here.",v3="";
//first : get v2.
SqlCommand cmd= new SqlCommand("select c2 from t2 where c3=$v2", conn); // using the v2 query you stated.
cmd.Parameters.AddWithValue("$v2", v2);
cmd.ExecuteNonQuery();
// put the value from the query into v3
// then, make the entire, bigger query
string finalQuery = "INSERT INTO t1 VALUES($v1,$v2)";
SqlCommand cmd2= new SqlCommand(finalQuery, conn);
cmd2.Parameters.AddWithValue("$v1", v1);
cmd2.Parameters.AddWithValue("$v2", v3);
cmd2.ExecuteNonQuery();
Обратите внимание, что депараметризация значений $v1 и $v2 решает проблему, но просто параметризация одного из двух вызывает проблему.
ИЗМЕНИТЬ 2:
В чате мы посмотрели дальше на ошибку компиляции, так как было какое-то странное поведение с параметризацией разных значений. Я спросил вас, какие значения находятся в $v1
и $v2
, и мы выяснили, что nvarchar
в v2
неверно интерпретируется как псевдоимя. Это также объясняет, почему SQL работает, а C# не работает; на самом деле ошибка заключалась в том, как OleDB интерпретировала имя. Решение простое — добавьте метки '
до и после v2,
, что приведет к тому, что оно будет прочитано как непсевдострока, например: "INSERT INTO t1 select $v1,c2 FROM t2 WHERE c3= '$v2'"
.
person
A. Abramov
schedule
14.08.2015