SqlDataAdapter.Update批量数据更新

时间:2022-09-21 21:39:45
SqlDataAdapter.Update批量数据更新

使用SqlDataAdapter.Update可以方便地对数据库进行快速、批量数据更新。我们最常用的多条数据更新方法是使用循环多次执行SQL语句或存储过程,这样虽然方便,但由于连接和数据传递要在服务器和客户端多次来往,大大增加了整个过程的时间,当数据越大时越明显!

下面对SqlDataAdapter.Update作个简单的演示介绍吧。

测试环境:SqlServer2008+VS2010+WinXP

1.建立测试数据库和表

CREATE DATABASE [TEST]
GO

USE [Test]
GO

CREATE TABLE [Student](
    [SNo] [int] NOT NULL,
    [SName] [nvarchar](50) ,
    [SAge] [int]
) O
GO

2.建立解决方案和项目

使用SqlDataAdapter.Update更新有三种方式,即SqlCommandBuiler自动生成更新,使用配置数据源方式更新,手动编写命令。

SqlCommandBuiler方式:

代码1:

private void Form1_Load(object sender, EventArgs e)
        {
            string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //设置select查询命令,SqlCommandBuilder要求至少有select命令
            SqlCommand selectCMD = new SqlCommand("select top 0 SNo,SName,SAge from Student", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            //上面的语句中使用select 0,不是为了查询出数据,而是要查询出表结构以向DataTable中填充表结构
            sda.Fill(dt);
            //给DataTable添加10条记录
            for(int i=1;i<=10;i++)
            dt.Rows.Add(new object[] { i, "aaa"+i, 20+i });
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //执行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();
            
        }

//执行后查看表中数据,如图:

SqlDataAdapter.Update批量数据更新
上面我只作了插入操作,那现在将Select中的Top 0 去掉,把表中的数据全部加载到DataTable然后执行删除和更新操作

代码2

private void Form1_Load(object sender, EventArgs e)
        {

string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //设置select查询命令,SqlCommandBuilder要求至少有select命令
            SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            //上面的语句中使用select 0,不是为了查询出数据,而是要查询出表结构以向DataTable中填充表结构
            sda.Fill(dt);
            //先更新第1,2条数据的SName和SAge
            dt.Rows[0]["SName"] = "AAA";
            dt.Rows[0]["SAge"] = 33;
            dt.Rows[1]["SName"] = "BBB";
            dt.Rows[1]["SAge"] = 444;
            //然后使用RemoveAt删除第3,4条数据
            dt.Rows.RemoveAt(2);
            dt.Rows.RemoveAt(3);
            //使用Delete删除
            //dt.Rows[2].Delete();
            //dt.Rows[3].Delete();
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //执行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();

}

执行后将出错,错误信息“对于不返回任何键列信息的 SelectCommand,不支持 UpdateCommand 的动态 SQL 生成。”

出错原因是建表时没有设置主键。主键唯一标识一行数据,SqlCommandBuilder是根据DataTable每行的RowState及对应的主键来生成命令的,没有主键就无法确定删除哪条数据,当然不可能根据其他列来删除,因为其他列可能重复,这样会删除多行数据,很可能执行后不是你想要的结果,这种不确定性的对数据的操作方法,微软当然不可能提供给你!

那就给表添加主键吧

执行如下SQL语句:
alter table student
add constraint PK_Student
primary key(SNo)

再次执行上面的代码2.

执行后

SqlDataAdapter.Update批量数据更新
我们发现第1,2行数据更新了,但是第3,4行却没有删除。这是怎么回事呢?

先不急,把代码2中的

dt.Rows.RemoveAt(2);
  dt.Rows.RemoveAt(3);

注释掉,同时把

//dt.Rows[2].Delete();
   //dt.Rows[3].Delete();

的注释去掉,使之执行Delete方法而不是RemoveAt方法

再看看结果:

SqlDataAdapter.Update批量数据更新

第3,4行已经删除。

原因是:使用RemoveAt或Remove会将数据真正的从DataTable中删除,而使用Delete则不会,而仅是把当前行的RowState值置为deleted.

前面说过SqlCommandBuilder是根据RowState和主键来生成命令的,RemoveAt/Remove把数据删除了,怎么能找到主键和RowState呢?

所以使用SqlCommandBuilder时应该注意的2点:表要有主键,应使用delete方法删除行.

手写命令方法:

代码3:

private void Form1_Load(object sender, EventArgs e)
        {
            string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //设置select查询命令
            SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);
            //Insert命令
            SqlCommand insertCMD = new SqlCommand("insert into Student(SNo,SName,SAge) values(@SNo,@SName,@SAge)", conn);
            //Update命令
            SqlCommand updateCMD = new SqlCommand("update Student Set SName=@SName,SAge=@SAge where SNo=@SNo", conn);
            //Delete命令
            SqlCommand deleteCMD = new SqlCommand("delete from Student where SNo=@SNo", conn);

//给Insert,Update,Delete三个命令添加参数
            SqlParameter paraSNo1, paraSNo2, paraSNo3;//第二个指定参数值的来源,这里的SNo是指DataTable中的列名
            paraSNo1 = new SqlParameter("@SNo", "SNo");
            paraSNo2 = new SqlParameter("@SNo", "SNo");
            paraSNo3 = new SqlParameter("@SNo", "SNo");
            paraSNo1.SourceVersion = DataRowVersion.Current;//指定SourceVersion确定参数值是列的当前值(Current),还是原始值(Original),还是建议值(Proposed)
            paraSNo2.SourceVersion = DataRowVersion.Current;
            paraSNo3.SourceVersion = DataRowVersion.Current;

SqlParameter paraSName1, paraSName2, paraSName3;
            paraSName1 =  new SqlParameter("@SName", "SName");
            paraSName2 = new SqlParameter("@SName", "SName");
            paraSName3 = new SqlParameter("@SName", "SName");
            paraSName1.SourceVersion = DataRowVersion.Current;
            paraSName2.SourceVersion = DataRowVersion.Current;
            paraSName3.SourceVersion = DataRowVersion.Current;

SqlParameter paraSAge1, paraSAge2, paraSAge3;
            paraSAge1 = new SqlParameter("@SAge", "SAge");
            paraSAge2 = new SqlParameter("@SAge", "SAge");
            paraSAge3 = new SqlParameter("@SAge", "SAge");
            paraSAge1.SourceVersion = DataRowVersion.Current;
            paraSAge2.SourceVersion = DataRowVersion.Current;
            paraSAge3.SourceVersion = DataRowVersion.Current;

insertCMD.Parameters.AddRange(new SqlParameter[] { paraSNo1, paraSName1, paraSAge1 });
            updateCMD.Parameters.AddRange(new SqlParameter[] { paraSNo2, paraSName2, paraSAge2 });
            deleteCMD.Parameters.AddRange(new SqlParameter[] { paraSNo3, paraSName3, paraSAge3 });

DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            sda.Fill(dt);
            //插入2条数据
            dt.Rows.Add(new object[] { 11, "aa11", 31 });
            dt.Rows.Add(new object[] { 12, "aa12", 32 });

//先更新第1,2条数据的SName和SAge
            dt.Rows[0]["SName"] = "CCC";
            dt.Rows[0]["SAge"] = 55;
            dt.Rows[1]["SName"] = "DDD";
            dt.Rows[1]["SAge"] = 66;

//使用Delete删除第3,4条数据
            dt.Rows[2].Delete();
            dt.Rows[3].Delete();
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //执行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();
        }

执行结果:

SqlDataAdapter.Update批量数据更新

可以看到

第SNo为11,12的数据是新增的。

原来SNo为1,2的数据中SName已经从AA,BB更改为CC,DD,另一列SAge从33,44更改为55,66。

原来SNo为5,6也就是第3,4条数据已经被删除

//

原文链接:http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263992.html

SqlDataAdapter.Update批量数据更新的更多相关文章

  1. SqlBulkCopy&lpar;批量复制&rpar;使用方法 &amp&semi;&amp&semi; SqlDataAdapter Update

    SqlBulkCopy提供了一种将数据复制到Sql Server数据库表中高性能的方法.SqlBulkCopy 包含一个方法 WriteToServer,它用来从数据的源复制数据到数据的目的地. Wr ...

  2. 【C&num;-批量插入数据到数据库】DataTable数据批量插入数据的库三种方法:SqlCommand&period;EcecuteNonQurery&lpar;&rpar;,SqlDataAdapter&period;Update&lpar;DataTable&rpar; ,SqlBulkCopy&period;WriteToServer&lpar;Datatable&rpar;

    第一种方法:使用SqlCommand.EcecuteNonQurery()  效率最慢 第二种方法:使用SqlDataAdapter.Update(DataTable)   效率次之 第三种方法:使用 ...

  3. sql server merge into 与update 批量更新1 百万测试数据的性能比较

    1. 1百万的测试数据的生成 declare @index int;  begin  set @index=0;  while @index<1000000  begin  insert int ...

  4. update批量更新某一列成其它列对应的值【原】

    update批量更新某一列成其它列对应的值 postgresql 标准sql语句 update AA set name = BB.name , AA.sex = BB.sex from BB wher ...

  5. 批量 1 insert into select 2 sqldataadapter&period;update 3 SELECT INTO FROM &lpar;要求目标表不存在&rpar; 4 AddRange&lpar;ef&rpar; 5 MySqlBulkLoader&period;Load&lpar;&rpar; 6 BatchInsert 7 insert bulk

     insert into a(col1,col2) select top 1 '1','2' from a union select top 1 '3','4' from a    SELECT IN ...

  6. SqlDataAdapter&period;Update&lpar;&rpar;方法与SqlCommandBuilder&lpar;转&rpar;

    用SqlDataAdapter操纵数据集时最常用到的就是Fill()与Update()方法.Fill()填充DataSet或DataTable,而Update()就是将DataSet或DataTabl ...

  7. hisql orm update表数据更新文档

    更新 HiSql数据更新 HiSql 提供了好几种数据更新的方式下面一一介绍一下 如果你的表中增加了这四个字段 字段 描述 类型 CreateTime 创建时间 DateTime CreateName ...

  8. Oracle forall bulk collect批量数据更新

    对于数据量较大的插入操作可采用此种方法操作,注意: limit减少内存占用,如果数据量较大一次性全部加载到内存中,对PGA来说压力太大,可采用limit的方法一次加载一定数量的数据,建议值通常为100 ...

  9. 【转】【MySql】Update批量更新与批量更新多条记录的不同值实现方法

    批量更新 mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other ...

随机推荐

  1. Hibernate &commat;OneToMany等注解设置查询过滤条件等

    1.如实体PdOrg对象中有users对象,数据库user表有字段DEL_FLAG(0:删除:1:未删除): private List<User> users= new ArrayList ...

  2. C&num; Graphics类详解

    转自于:http://blog.163.com/gis_warrior/blog/static/19361717320119227034181/ Brush 类.NET Framework 4定义用于 ...

  3. android ViewGroup事件分发机制

    1:事件分销过程 自定义一个LinearLayout,重写dispatchTouchEvent onInterceptTouchEvent onTouchEvent,定义一个按键重写dispathcT ...

  4. 使用qmake生成Makefile

    Qmake自动生成Makefile 手动写Makefile是一件痛苦的事情,稍不小心就会出错,不过qmake可以让你脱离苦海 qmake可以根据你提供的.pro文件,生成Makefile不过他可比Ma ...

  5. C&plus;&plus;&sol;C常量

    简介 1. 易忽略的常量:函数地址(函数名).静态数组的名字.字符串常量的地址. 2. 常量分类:字面常量.符号常量.契约性常量.布尔常量.枚举常量. 常量认知 1. 字面常量 包括:各种进制的数字. ...

  6. fiddler 路由设置

    REGEX:^http://data.51buy.com/biz/oppmsmobile/web/js/app/(.+)/(.+).js E:\svns\new\dev\webapp\data_ics ...

  7. 【转】DELL R710服务器可以安装的VMWare ESX Server 4&period;1 全套下载带注册码

    随着R710的停产,R720随之面世,但DELL R720服务器只支持vmware esxi5.0以上,DELL客户经理给了一套系统安装后序列号无法解决,还是用4.1好了,却又发现怎么都无法安装.按网 ...

  8. MySQL实现差集&lpar;Minus&rpar;和交集&lpar;Intersect&rpar;

    原文链接: http://www.linuxidc.com/Linux/2014-06/103551.htm MySQL没有实现Minus和Intersect功能,就像它也没有实现cube的功能一样. ...

  9. css中的注意项,可能会帮助到大家哦!

    CSS样式层叠表 1.link与@import的区别(5点) (1).link为XHTML的标签,可以引进CSS样式表,除了引进CSS文件还可以引进其他的文件如.js或.rss文件;@import为C ...

  10. emptyDir与hostPath

    目录 Volume类型 emptyDir hostPath Volume类型 volume是kubernetes Pod中多个容器访问的共享目录.volume被定义在pod上,被这个pod的多个容器挂 ...