C# 插入多列
我目前需要在数据库中插入一行,但我有很多列,总共11列(没有ID)。我正在使用以下命令:C# 插入多列,c#,sql,ado.net,C#,Sql,Ado.net,我目前需要在数据库中插入一行,但我有很多列,总共11列(没有ID)。我正在使用以下命令: INSERT INTO table1 (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11) VALUES (@par1, @par2, @par3, @par4, @par5, @par6, @par7, @par8, @par9, @par10, @par11) 但正如您所看到的,它太长了,我无法避免
INSERT INTO table1 (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11) VALUES (@par1, @par2, @par3, @par4, @par5, @par6, @par7, @par8, @par9, @par10, @par11)
但正如您所看到的,它太长了,我无法避免使用列名,因为我仍然有ID。有没有更有效的方法来插入?或者是一种缩短它的方法?因为按照我的方式,我还必须一个接一个地添加参数,如下所示:
myCommand.Parameters.Add(value1, "@par1");
这与用任何其他语言填充任何数据结构的成员没有太大区别。如果没有填充数据结构的每个成员,则必须指定要填充的每个成员,是使用基于集合的方式(如SQL)指定它,还是使用单独的属性值对(如
set object.attribute=value
)
但是,与任何其他语言一样,您可以编写一个函数或过程来隐藏其中的一些细节,这样您只需要传入适当的变量。然后,对于任何给定场景,您只需写出一次所有详细代码。将所有值放入一个列表,并使用for循环,然后在编辑中逐个插入列表值:再次感谢@Sentinel提醒我注意潜在的安全风险。这种方法与语言无关,但我同意他的建议,即您也可以使用
myCommand.Parameters.Add(values[N],“@parN”)代码>而不是为值构建字符串
扩展@Javies Inusti答案
这个答案假设您正在使用字符串来构建SQL查询
这是一个常见且易于处理的场景。最简单的处理方法(imho)是在字符串中使用标记,创建列和值的数组/列表,并用这些数组/列表的内容替换标记
using System;
class Program
{
//defining a blacklist of unwanted terms that should not appear in your column names or value strings
//This is just for the sake of the example, and there are definitely some statements missing in this array
static string[] QUERY_BLACKLIST = { "SELECT", "DROP", "INSERT", "DELETE", "UPDATE" };
static void Main(string[] args)
{
//Use markers in your query string
string query = "INSERT INTO table (:columns:) VALUES (:values:);";
//define an array of column names to insert for the :columns: marker
string[] columns = { "ID", "Name", "Age", "Something"};
//some dummy values. Real code would use a model or something to that effect
int id = 9;
string name = "John";
int age = 12;
bool something = true;
//all values should be passed as strings, they will replace the :values: marker
string[] values = { id.ToString(), name, age.ToString(), something.ToString()};
query = Program.FillColumnsIntoQuery(query, columns, values);
Console.WriteLine(query);
//Output:
//"INSERT INTO table (ID,Name,Age,Something) VALUES ('9','John','12','true');"
//example for the blacklist check
query = "INSERT INTO table (:columns:) VALUES (:values:);";
//strings with malicious intent behind them
string[] columns2 = { "DROP table" };
string[] values2 = { "DELETE * FROM table" };
try
{
query = Program.FillColumnsIntoQuery(query, columns2, values2);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//Output:
//"Someone is trying to do evil stuff!"
}
Console.ReadLine();
}
public static string FillColumnsAndValuesIntoInsertQuery(string query, string[] colums, string[] values)
{
//joining the string arrays with a comma character
string columnnames = string.Join(",", colums);
//adding values with single quotation marks around them to handle errors related to string values
string valuenames = "'" + string.Join("','", values) + "'"; ;
//we need to check every entry of the blacklist against the provided strings
foreach(string blacklist in QUERY_BLACKLIST)
{
if(columnnames.ToLower().IndexOf(blacklist.ToLower()) >= 0
|| valuenames.ToLower().IndexOf(blacklist.ToLower()) >=0)
{
throw new Exception("Someone is trying to do evil stuff!");
}
}
//replacing the markers with the desired column names and values
return query.Replace(":columns:",columnnames).Replace(":values:", valuenames);
}
}
如果您想变得有趣,可以为string类编写一个扩展方法。你也可以通过标记。您可以编写函数为您构建查询模板。您可以为函数选择一个较短的名称
可能性是无穷的:-)。“但正如你所看到的,它太大了”-你这是什么意思?在什么意义上太大了?真的不清楚你在问什么。@JonSkeet我的意思是它很长,如果我有一个25列的数据库,它的效率很低。例如,只写一行并添加参数需要很长时间。你真的担心键入代码的效率,还是执行时间的效率?当然,如果你有很多值,那最终会变成更多的代码,但我并不认为这里有什么问题。@JonSkeet嗯,我假设我有有限的时间使用ADO.NET在数据库中进行基本操作,但是数据库有3个表,每个表都有很多列。这件事发生在我几周前,我正试图解决这个问题。在你花时间问这个问题的时候,你可能已经为insert语句编写了代码。说真的,如果这方面占了你整个应用程序编写时间的很大一部分,我会感到非常惊讶。我认为为了清晰起见,你应该用“列名”替换“值”。否则我会这样做。你需要小心使用动态SQL。恶意用户可能会提供破坏动态生成的查询的输入,从而产生意外结果。因此,最好保持查询参数化,但您仍然可以在数组中循环查找值,构建参数名称列表并使用myCommand.parameters.Add(值[N],“@parN”)
将名称映射到参数。@Sentinel很好,我完全忘记了。为了安全起见,您可以尝试绝对确保列名和值字符串不包含任何类型的SQL语句。这实际上意味着一个额外的数组,在连接列和值之前循环遍历这些列和值,并针对不需要的术语的黑名单执行indexOf检查。这很重要,谢谢你提醒我。