使用未知名称/参数数量更新sql语句

本文关键字:数数 更新 sql 语句 参数 未知 | 更新日期: 2023-09-27 18:29:12

我有一个经典的ASP网站,我正在慢慢升级。我想创建一个函数来安全地更新SQL数据库,而无需手动指定参数。一些更具活力的东西。

(我不想使用实体框架或Linq)

这是迄今为止的代码:

string updateSql = "UPDATE sometable" + "SET test1= @testData1 " + "WHERE a = @aData1";
SqlCommand UpdateCmd = new SqlCommand(updateSql, conn);
UpdateCmd.Parameters.Add("@testData1 ", SqlDbType.NVarChar, 10, "testData1 ");
UpdateCmd.Parameters.Add("@aData1", SqlDbType.NVarChar, 20, "aData1");
UpdateCmd.Parameters["@testData1 "].Value = "21515";
UpdateCmd.Parameters["@aData1"].Value = "32t3t";
UpdateCmd.ExecuteNonQuery();

伪代码(我想要实现的)

创建一个覆盖所有变量的Ilist{get;set:}[validate type/length]

对于每个包含值(没有验证问题)的变量,创建sql更新字符串。

执行它。

可能的问题:我能预见的唯一问题是,列表可能有500个变量,但每个SQL更新可能只有2或3列被更新。这不是有效的吗?

使用未知名称/参数数量更新sql语句

您需要做这样的事情。。。。显然需要更多的编码。。。。

 static void Main(string[] args)
    {
        var values = new Dictionary<string, object>( );
        values.Add( "name", "timmerz" );
        values.Add( "dob", DateTime.Now );
        values.Add( "sex", "m" );
        SqlUpdate( "sometable", values );
    }
    public static void SqlUpdate( string table, Dictionary<string,object> values, string where )
    {
        var equals      = new List<string>( );
        var parameters  = new List<SqlParameter>( );
        var i = 0;
        foreach( var item in values )
        {
            var pn = "@sp" + i.ToString( );
            equals.Add( string.Format( "{0}={1}", item.Key, pn ) );
            parameters.Add( new SqlParameter( pn, item.Value ) );
            i++;
        }
        string command = string.Format( "update {0} set {1} where {2}", table, string.Join( ", ", equals.ToArray( ) ), where );
        var sqlcommand = new SqlCommand(command);
        sqlcommand.Parameters.AddRange(parameters.ToArray( ) );
        sqlcommand.ExecuteNonQuery( );
    }

我不确定我是否完全理解您想要做什么,但这可能接近您想要的。您可以创建一个任意长的参数和相应值的列表,然后根据该列表动态构建相应的UPDATE

//set up SqlCommand
SqlCommand UpdateCmd = new SqlCommand();
UpdateCmd.Connection = conn;
//build your dictionary (probably happens elsewhere in your code)
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("col1", "col1 value");
parameters.Add("col2", 42);
parameters.Add("col3", DateTime.Now);
//build a command string and add parameter values to your SqlCommand
StringBuilder builder = new StringBuilder("UPDATE sometable SET ");
foreach(KeyValuePair<string, object> parameter in parameters) {
    builder.Append(parameter.Key).Append(" = @").Append(parameter.Key).Append(",");
    UpdateCmd.Parameters.AddWithValue("@" + parameter.Key, parameter.Value);
}
builder.Remove(builder.Length - 1,1);
//set the command text and execute the command
UpdateCmd.CommandText = builder.ToString();
UpdateCmd.ExecuteNonQuery();

如果您使用的是SQL Server 2008,您可以选择将参数及其值作为表传递给存储过程。在存储过程中,您可以使用传入的表连接要更新的表。这可能比创建数百个sep-update语句更有效。这里有一个可能有帮助的链接http://msdn.microsoft.com/en-us/library/bb675163.aspx这里有一些基于你在问题中发布的代码的示例代码

首先创建一个要玩的表,并用一些数据填充它

CREATE TABLE [dbo].[sometable](
    [Test1] [nvarchar](100) NULL,
    [a] [nvarchar](100) NULL
) ON [PRIMARY]
Insert sometable Select 'rerere', '122342'
Insert sometable Select 'sfsfw', '343'
Insert sometable Select 'sfdrgss', '434545'
Insert sometable Select 'srgegrgeg', '3939932'

然后在SQL Server 中创建类型

Create TYPE dbo.ParamsType AS TABLE
( Test1 nvarchar(100), a nvarchar(100) )

然后创建接受该类型作为参数的存储过程

    CREATE PROCEDURE usp_UpdateSomeTable 
@Parameters dbo.ParamsType READONLY
AS
BEGIN
    SET NOCOUNT ON;
UPDATE sometable
    SET sometable.Test1 = p.Test1
    FROM sometable INNER JOIN @Parameters as p
    ON sometable.a = p.a;
END
GO

要从SQL Server Management Studio进行测试,可以运行

Declare @t as ParamsType
Insert @t Select 'newValue1', '122342'
Insert @t Select 'morenew ', '343'
Insert @t Select 'again', '434545'
Insert @t Select 'OnceMore', '3939932'
exec usp_UpdateSomeTable @Parameters=@t

要从C#测试,请尝试

        static void Main(string[] args)
        {
            System.Data.DataTable YourData = new DataTable("Parameters");
            DataColumn column;
            DataRow row;
            column = new DataColumn();
            column.DataType = System.Type.GetType("System.String");
            column.ColumnName = "Test1";
            YourData.Columns.Add(column);
            column = new DataColumn();
            column.DataType = System.Type.GetType("System.String");
            column.ColumnName = "a";
            YourData.Columns.Add(column);
            row = YourData.NewRow();
            row["Test1"] = "newValue1";
            row["a"] = "122342";
            YourData.Rows.Add(row);
            row = YourData.NewRow();
            row["Test1"] = "morenew";
            row["a"] = "343";
            YourData.Rows.Add(row);
            row = YourData.NewRow();
            row["Test1"] = "again";
            row["a"] = "434545";
            YourData.Rows.Add(row);
            SqlConnectionStringBuilder connString = new SqlConnectionStringBuilder();
            connString.DataSource = "127.0.0.1";
            connString.InitialCatalog = "SO";
            connString.IntegratedSecurity = true;
            using (SqlConnection conn = new SqlConnection())
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.CommandText = "usp_UpdateSomeTable";
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                SqlParameter p = cmd.Parameters.AddWithValue("@Parameters", YourData);
                p.SqlDbType = SqlDbType.Structured;
                p.TypeName = "dbo.ParamsType";
                cmd.Connection = conn;
                conn.ConnectionString = connString.ConnectionString;
                conn.Open();
                cmd.ExecuteNonQuery();
            }
        }