转载自:http://www.cnblogs.com/chinahnzl/articles/968649.html

问题
CSDN 里面不时有初学者疑惑:如何获取自增长列(标识列)的ID,并写入另一张表。
场景
这里选择典型的多对多关系,并以常见的 User-Role 作为 Demo,同时显示 Access 和 Sql Server 版本
关系图

实现要点
1, 如何获取新插入记录生成的 ID:Sql Server 和 Access(当使用 Jet ADO,当然包括ADO.NET,连接时)均支持 @@Identity 全局变量,返回在当前会话的所有表中生成的最后一个标识值
2,同时写入多张表需要显示使用事务

MS Access 版本

@@identity是表示的是最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,是系统定义的全局变量。一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头。比如有个表A,它的自增列是id,当向A表插入一行数据后,如果插入数据后自增列的值自动增加至101,则通过select @@identity得到的值就是101。使用@@identity的前提是在进行insert操作后,执行select @@identity的时候连接没有关闭,否则得到的将是NULL值。

INSERT INTO table(field1,field2,...) VALUES("field1Value","field2Value",...) SELECT IDENT_CURRENT('recordID') as newIDValue
INSERT INTO table(field1,field2,...) VALUES("field1Value","field2Value",...) SELECT SCOPE_IDENTITY() as newIDValue
INSERT INTO table(field1,field2,...) VALUES("field1Value","field2Value",...) SELECT @@IDENTITY as newIDValue

ACCESS中的@@IDENTITY由于ACCESS不允许使用“;”来分隔多条SQL语句进行执行,并且在执行两次OleDbCommand时后一个SELECT与前一个INSERT已经没什么关系了,所以在这使用 "select @@identity from [表名] " 将会得到的值为 0,这并不是我们所想得到的值,所以在ACCESS中如果想要得到 @@identity 的值,就可以使用事务来进行解决:

/// <summary>
/// 执行事务获取最新的ID
/// </summary>
/// <param name="cmdText"></param>
/// <returns></returns>
public int GetIdentity(string cmdText)
{
using (OleDbConnection oleCon = new OleDbConnection(connectionString))
{
oleCon.Open();
OleDbCommand cmd = new OleDbCommand();//创建一个cmd
OleDbTransaction trans = oleCon.BeginTransaction();//创建事务
cmd.Connection = oleCon;//cmd连接
cmd.Transaction = trans;//cmd的事务
try
{
cmd.CommandText = cmdText;//执行的SQL语句
cmd.ExecuteNonQuery();//执行insert 语句
cmd.CommandText = "select @@identity from [表名] ";//执行SQL,获取新增ID
trans.Commit();//提交事务
int i = Convert.ToInt32(cmd.ExecuteScalar());//执行Select @@identity 语句,获取id值
return i;//将Id值返回
}
catch
{
trans.Rollback();//如果发生异常,回滚事务
return -;//返回-1
}
finally
{
oleCon.Close();//关闭数据源
}
}
}
 <%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> string connStr; protected void Page_Load(object sender, EventArgs e)
{
connStr = "provider=Microsoft.Jet.OleDb.4.0;data source=" + Server.MapPath("~/App_Data/DemoManyToMany.mdb");
} protected void btnLogin_Click(object sender, EventArgs e)
{
if (chkRoles.SelectedIndex == -) throw new Exception("至少选择一个角色。"); string sqlInserUser = "INSERT INTO [User]([UserName], [Password]) VALUES(?, ?)";
string sqlInserUserRoel = "INSERT INTO UserRole([UserId], [RoleId]) VALUES(?, ?)";
string sqlSelectNewUserId = "SELECT @@Identity"; // OR "SELECT MAX([UserId]) FROM [User]";
using (OleDbConnection conn = new OleDbConnection(connStr)) {
conn.Open();
// 显示开启事务
OleDbTransaction trans = conn.BeginTransaction();
OleDbCommand cmd = conn.CreateCommand();
// 关联事务
cmd.Transaction = trans; try {
cmd.CommandText = sqlInserUser;
cmd.Parameters.Add("UserName", txtUserName.Text);
cmd.Parameters.Add("Password", txtPassword.Text);
// 插入 User
cmd.ExecuteNonQuery(); cmd.CommandText = sqlSelectNewUserId;
// 读取新插入 UserId
int newUserId = (int)cmd.ExecuteScalar(); // 仅供测试
if (chkGeneratError.Checked) throw new Exception("创建用户时发生错误。"); cmd.CommandText = sqlInserUserRoel;
cmd.Parameters.Clear();
cmd.Parameters.Add("UserId", OleDbType.Integer);
cmd.Parameters.Add("RoleId", OleDbType.Integer);
cmd.Parameters[].Value = newUserId;
// 遍历可选角色列表
foreach (ListItem item in chkRoles.Items) {
if (item.Selected) {
cmd.Parameters[].Value = item.Value;
// 写入中间关系表 UserRole
cmd.ExecuteNonQuery();
}
}
// 提交事务
trans.Commit();
lblMsg.Text = String.Format("用户 '{0}' 创建成功。\n事务已提交。", txtUserName.Text);
}
catch(Exception inner) {
// 发生错误,回滚事务
if (trans != null) trans.Rollback();
lblMsg.Text = String.Format("用户 '{0}' 创建失败。\n事务已回滚。\n详细信息:{1}", txtUserName.Text, inner.Message);
//throw new Exception("创建用户失败。事务已回滚。", inner);
}
}
// 重新加载 User 数据
grdvUsers.DataBind();
} protected void grdvUsers_RowDataBound(object sender, GridViewRowEventArgs e)
{
// 加载每个 User 对应的 Roles
DataList dlstRolesOfUser = e.Row.FindControl("dlstRolesOfUser") as DataList;
if(dlstRolesOfUser == null) return; int userId = (int)grdvUsers.DataKeys[e.Row.RowIndex].Value; string sqlSelectRoleOfUser =
"SELECT Role.RoleName FROM (Role INNER JOIN UserRole ON Role.RoleId = UserRole.RoleId) WHERE UserRole.UserId=?";
OleDbDataAdapter da = new OleDbDataAdapter(sqlSelectRoleOfUser, connStr);
da.SelectCommand.Parameters.Add("UserId", userId);
DataTable dtRolesOfUser = new DataTable();
da.Fill(dtRolesOfUser);
dlstRolesOfUser.DataSource = dtRolesOfUser;
dlstRolesOfUser.DataBind();
} </script> <html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>多对多写入实例——Access版本</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>多对多写入实例——Access版本</h1>
<h3>创建用户</h3>
<table border="">
<tr>
<td>
用户名:
</td>
<td>
<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtUserName"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td>
密码:
</td>
<td>
<asp:TextBox ID="txtPassword" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>
角色:
</td>
<td>
<asp:CheckBoxList ID="chkRoles" runat="server" DataSourceID="AccessDataSource1" DataTextField="RoleName" DataValueField="RoleId" RepeatDirection="Horizontal"></asp:CheckBoxList><asp:AccessDataSource ID="AccessDataSource1" runat="server" DataFile="~/App_Data/DemoManyToMany.mdb"
SelectCommand="SELECT [RoleId], [RoleName] FROM [Role]"></asp:AccessDataSource>
</td>
</tr>
<tr>
<td>
强制发生错误:
</td>
<td>
<asp:CheckBox ID="chkGeneratError" runat="server" /></td>
</tr>
<tr>
<td>
</td>
<td>
<asp:Button ID="btnLogin" runat="server" Text="确定" OnClick="btnLogin_Click" /></td>
</tr>
</table>
<pre><asp:Label ID="lblMsg" runat="server" ForeColor="red"></asp:Label></pre>
<br />
</div>
<h3>用户列表</h3>
<asp:GridView ID="grdvUsers" runat="server" AutoGenerateColumns="False" DataKeyNames="UserId"
DataSourceID="AccessDataSource2" OnRowDataBound="grdvUsers_RowDataBound">
<Columns>
<asp:BoundField DataField="UserId" HeaderText="UserId" InsertVisible="False" ReadOnly="True"
SortExpression="UserId" />
<asp:BoundField DataField="UserName" HeaderText="UserName" SortExpression="UserName" />
<asp:BoundField DataField="Password" HeaderText="Password" SortExpression="Password" />
<asp:TemplateField HeaderText="角色">
<ItemTemplate>
<asp:Datalist id="dlstRolesOfUser" runat="server" RepeatDirection="Horizontal">
<ItemTemplate><%# Eval("RoleName") %></ItemTemplate>
<AlternatingItemTemplate>,<%# Eval("RoleName") %></AlternatingItemTemplate>
</asp:datalist>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
暂无数据
</EmptyDataTemplate>
</asp:GridView>
<asp:AccessDataSource ID="AccessDataSource2" runat="server" DataFile="~/App_Data/DemoManyToMany.mdb"
SelectCommand="SELECT [UserId], [UserName], [Password] FROM [User]"></asp:AccessDataSource>
</form>
</body>
</html>

MS SQL Server 版本

 <%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> string connStr; protected void Page_Load(object sender, EventArgs e)
{
connStr = "server=.;database=DemoLib;uid=sa";
} protected void btnLogin_Click(object sender, EventArgs e)
{
if (chkRoles.SelectedIndex == -) throw new Exception("至少选择一个角色。"); string sqlInserUser = "INSERT INTO [User]([UserName], [Password]) VALUES(@UserName, @Password) SELECT @NewUserId=@@Identity";
string sqlInserUserRoel = "INSERT INTO UserRole([UserId], [RoleId]) VALUES(@UserId, @RoleId)";
string sqlSelectNewUserId = "SELECT @@Identity"; // OR "SELECT MAX([UserId]) FROM [User]";
using (SqlConnection conn = new SqlConnection(connStr)) {
conn.Open();
// 显示开启事务
SqlTransaction trans = conn.BeginTransaction();
SqlCommand cmd = conn.CreateCommand();
// 关联事务
cmd.Transaction = trans; try {
cmd.CommandText = sqlInserUser;
cmd.Parameters.Add("UserName", txtUserName.Text);
cmd.Parameters.Add("Password", txtPassword.Text);
// 此输出参数返回新插入 UserId
cmd.Parameters.Add("NewUserId", SqlDbType.Int).Direction = ParameterDirection.Output;
// 插入 User
cmd.ExecuteNonQuery(); /**//* 以下方法依然有效,只是我们选择更加简便方法:批处理SQL语句
cmd.CommandText = sqlSelectNewUserId;
// 读取新插入 UserId
int newUserId = (int)cmd.ExecuteScalar();
*/
int newUserId = (int)cmd.Parameters["NewUserId"].Value; // 仅供测试
if (chkGeneratError.Checked) throw new Exception("创建用户时发生错误。"); cmd.CommandText = sqlInserUserRoel;
cmd.Parameters.Clear();
cmd.Parameters.Add("UserId", SqlDbType.Int);
cmd.Parameters.Add("RoleId", SqlDbType.Int);
cmd.Parameters[].Value = newUserId;
// 遍历可选角色列表
foreach (ListItem item in chkRoles.Items) {
if (item.Selected) {
cmd.Parameters[].Value = item.Value;
// 写入中间关系表 UserRole
cmd.ExecuteNonQuery();
}
}
// 提交事务
trans.Commit();
lblMsg.Text = String.Format("用户 '{0}' 创建成功。\n事务已提交。", txtUserName.Text);
}
catch(Exception inner) {
// 发生错误,回滚事务
if (trans != null) trans.Rollback();
lblMsg.Text = String.Format("用户 '{0}' 创建失败。\n事务已回滚。\n详细信息:{1}", txtUserName.Text, inner.Message);
//throw new Exception("创建用户失败。事务已回滚。", inner);
}
}
// 重新加载 User 数据
grdvUsers.DataBind();
} protected void grdvUsers_RowDataBound(object sender, GridViewRowEventArgs e)
{
// 加载每个 User 对应的 Roles
DataList dlstRolesOfUser = e.Row.FindControl("dlstRolesOfUser") as DataList;
if(dlstRolesOfUser == null) return; int userId = (int)grdvUsers.DataKeys[e.Row.RowIndex].Value; string sqlSelectRoleOfUser =
"SELECT Role.RoleName FROM (Role INNER JOIN UserRole ON Role.RoleId = UserRole.RoleId) WHERE UserRole.UserId=@UserId";
SqlDataAdapter da = new SqlDataAdapter(sqlSelectRoleOfUser, connStr);
da.SelectCommand.Parameters.Add("UserId", userId);
DataTable dtRolesOfUser = new DataTable();
da.Fill(dtRolesOfUser);
dlstRolesOfUser.DataSource = dtRolesOfUser;
dlstRolesOfUser.DataBind();
} </script> <html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>多对多写入实例——SqlServer版本</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>多对多写入实例——SqlServer版本</h1>
<h3>创建用户</h3>
<table border="">
<tr>
<td>
用户名:
</td>
<td>
<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtUserName"
Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td>
密码:
</td>
<td>
<asp:TextBox ID="txtPassword" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>
角色:
</td>
<td>
<asp:CheckBoxList ID="chkRoles" runat="server" DataSourceID="SqlDataSource1" DataTextField="RoleName" DataValueField="RoleId" RepeatDirection="Horizontal"></asp:CheckBoxList><asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="Data Source=.;Initial Catalog=DemoLib;Integrated Security=True"
ProviderName="System.Data.SqlClient" SelectCommand="SELECT [RoleId], [RoleName] FROM [Role]">
</asp:SqlDataSource>
</td>
</tr>
<tr>
<td>
强制发生错误:
</td>
<td>
<asp:CheckBox ID="chkGeneratError" runat="server" /></td>
</tr>
<tr>
<td>
</td>
<td>
<asp:Button ID="btnLogin" runat="server" Text="确定" OnClick="btnLogin_Click" /></td>
</tr>
</table>
<pre><asp:Label ID="lblMsg" runat="server" ForeColor="red"></asp:Label></pre>
<br />
</div>
<h3>用户列表</h3>
<asp:GridView ID="grdvUsers" runat="server" AutoGenerateColumns="False" DataKeyNames="UserId"
DataSourceID="SqlDataSource2" OnRowDataBound="grdvUsers_RowDataBound">
<Columns>
<asp:BoundField DataField="UserId" HeaderText="UserId" InsertVisible="False" ReadOnly="True"
SortExpression="UserId" />
<asp:BoundField DataField="UserName" HeaderText="UserName" SortExpression="UserName" />
<asp:BoundField DataField="Password" HeaderText="Password" SortExpression="Password" />
<asp:TemplateField HeaderText="角色">
<ItemTemplate>
<asp:Datalist id="dlstRolesOfUser" runat="server" RepeatDirection="Horizontal">
<ItemTemplate><%# Eval("RoleName") %></ItemTemplate>
<AlternatingItemTemplate>,<%# Eval("RoleName") %></AlternatingItemTemplate>
</asp:datalist>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
暂无数据
</EmptyDataTemplate>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="Data Source=.;Initial Catalog=DemoLib;Integrated Security=True"
ProviderName="System.Data.SqlClient" SelectCommand="SELECT [UserId], [UserName], [Password] FROM [User]">
</asp:SqlDataSource>
&nbsp;
</form>
</body>
</html>

转:获得数据库自增长ID(ACCESS)与(SQLSERVER)的更多相关文章

  1. Mybatis 插入后返回数据库自动增长ID

    MySQL和MSSQL返回主键方法 在personMap.xml中 <insert id="addPerson" parameterType="orm.Person ...

  2. 数据库自动增长id下一次的值

    mysql SELECT auto_increment FROM information_schema.`TABLES` WHERE TABLE_SCHEMA='my_db_name' AND TAB ...

  3. 利用数据库触发器让字段与自增长Id相关联

    十年河东,十年河西,莫欺少年穷 学无止境,精益求精 今天是数据库脚本类的代码,所以不想过多阐述 如下数据表: create table Card( Id ,) primary key, CardNo ...

  4. ID字段不采用数据库自增长的几点理由

    一个小程序,最初采用了 SqlServer 数据库,后来为了便于部署,转而采用了 Firebird 嵌入式数据库.在重构代码转到 Firebird 的过程中,对“数据实体的数据表的ID字段是否应该使用 ...

  5. C#实体类对应SQL数据库的自增长ID怎么设置?

    /// <summary> /// 自增长ID /// </summary> [DatabaseGenerated(DatabaseGeneratedOption.Identi ...

  6. mysql 数据库自增id 的总结

    有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...

  7. shell脚本获取mysql插入数据自增长id的值

    shell脚本获取mysql插入数据自增长id的值 在shell脚本中我们可以通过last_insert_id()获取id值,但是,需要注意的是,该函数必须在执行插入操作的sql语句之后,立即调用,否 ...

  8. Android在API推荐的方式来实现SQLite数据库的增长、删除、变化、检查操作

    package com.examp.use_SQLite.dao; import java.util.ArrayList; import java.util.List; import android. ...

  9. 关于MySql中自增长id设置初始值

    在MySQL数据库,设置了id为自增长类型,但由于程序还处于开发阶段,很容易的会产生错误数据,然后就直接删除了,可是id的自增长值没有跟着减少,这里提示: 如果表中数据没有用,直接删除了数据,自动增长 ...

随机推荐

  1. 原生js获取子元素、给元素增加div

    //鼠标移入移出动画 解决页面闪屏问题 window.onload = function () { var el = document.createElement('div'); el.classNa ...

  2. svn 客户端安装 windows

    windows使用的 https://tortoisesvn.net/ 下载中文语言包 安装 安装完安装语言包 看到这个代表svn客户端可以用了 windows客户端下载TortoiseSVN软件进行 ...

  3. spring boot 的使用

    一:首先安装spring boot插件 两种方式安装, 1:使用myeclipse自带的安装插件的功能 help>  install from catalog> 将出现下面的界面,搜寻sp ...

  4. Mongodb 基础 数据导入导出和用户管理

    数据导出 导出命令使用方式 mongoexport---->csv/json使用 参数: -d 库名 -c 表名 -f field1,field2....列名 -q 查询条件 -o 导出文件名 ...

  5. AD使用ntdsutil工具 恢复主域控制器 清理孤立域控制器

    需求: 主域控制器出现灾难故障,辅助域控制器正常 在辅助域控制器使用ntdsutil工具清理主域控制器并夺取PDC角色 首先清理孤立的域控制器 ntdsutil ntdsutil: metadata ...

  6. 【LeetCode每天一题】Find First and Last Position of Element in Sorted Array(找到排序数组中指定元素的开始和结束下标)

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  7. 23-Python3 File

    ''' file(文件)方法 ''' #open()对象 pass #file对象 ##file.close():关闭文件,关闭后不能再进行读写操作 fo1 = open('/Users/ligaij ...

  8. linux shell脚本检测硬盘磁盘空间 邮件报警

    使用 http://www.weiruoyu.cn/?p=368 shell脚本监控硬盘空间剩余空间 邮件报警 1.先观察一下磁盘,和如何使用脚本 [root@localhost ~]# df -h ...

  9. python string method

    嗯,学习其它语言没这样全练过,嘻嘻 //test.py 1 # -*- coding: UTF-8 -*- 2 3 str = "i am worker" 4 print str. ...

  10. iOS UI基础-9.0 UITableView基础

    在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView.UITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳. UITableView有两种样式: ...