动态网站制作指南
[  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库学院 > 数据库技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Access教程,DB2教程,数据库安全,数据库文摘
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ 数据库技巧 ]的信息

本月文章推荐
.解决SQL Server虚拟内存不足情况.
.向你推荐一个特别好用的分页存储.
.一些SQL Server的应用实例.
.sql server发送邮件.
.SQL Sever 2000中的前触发器和后.
.金额阿拉伯数字转换为中文的存储.
.精妙SQL语句收集.
.在SQL Server中建立定时任务,处.
.考虑SQL Server安全时所应注意的.
.使用 SQL Server 2005 数据库镜像.
.Replace INTO与INSERT INTO的不同.
.一個Select出一個表中第N條記錄的.
.有关读取SQL数据库里TEXT和NTEXT.
.如何使用系统管理员帐户管理多个.
.sql server 2000 游标用法小例.
.SQL Server 2000的数据转换服务(.
.SQL Server 2005中查询并修改数据.
.在SQL Server 2000里设置和使用数.
.sql server转换时间为字符串.
.net在sql server中的图片存取技术.

小议主子表INT自增主键插入记录的方法

文章类别:数据库技巧 | 发表日期:2005-7-3 |


       主子表最常见的大概就是用在进销存、MRP、ERP里面,比如一张销售订单,订单Order(ID,OrderDate),订单明细OrderDetail(OrderID, ProductID, Num,Price)这个大概就是最简单的主子表了,两个表通过ID与OrderID建立关联,这里主键ID是自增的INT类型,OrderID是表OrderDetail的外键。当然,键的选择方法很多,现在我们选择的是在sql里面最简单的方法。

    对于这样的表结构,我们最常见的问题就是保存的时候怎样处理键值的问题,因为两个表关联非常的紧密,我们进行保存的时候需要把它们放在一个事务里面,这时问题就会出现,Order表中的ID是自动增长型的字段。现在需要我们录入一张订单,包括在Order表中插入一条记录以及在OrderDetail表中插入若干条记录。因为Order表中的ID是自动增长型的字段,那么我们在记录正式插入到数据库之前无法事先得知它的取值,只有在更新后才能知道数据库为它分配的是什么值,然后再用这个ID作为OrderDetail表的OrderID的值,最后更新OderDetail表。但是,为了确保数据的一致性,Order与OrderDetail在更新时必须在事务保护下同时进行,即确保两表同时更行成功,这个就会有点困扰。


解决这类问题常见的主要有两类方法:


一种是微软在网上书店里使用的方法,使用了四个存储过程。改装一下,使之符合现在的例子


--存储过程一


CREATE PROCEDURE InsertOrder

 

    @Id                INT = NULL OUTPUT,

 

    @OrderDate        DATETIME = NULL,

 

    @ProductIDList     NVARCHAR(4000) = NULL,

 

    @NumList          NVARCHAR(4000) = NULL,

 

    @PriceList          NVARCHAR(4000) = NULL

 

AS

 

    SET NOCOUNT ON

 

    SET XACT_ABORT ON

 

    BEGIN TRANSACTION

 

   --插入主表

 

    INSERT Orders(OrderDate) select @OrderDate

 

     SELECT @Id = @@IDENTITY

 

      -- 插入子表

 

     IF @ProductIDList IS NOT NULL

 

            EXECUTE InsertOrderDetailsByList @Id, @ProductIdList, @numList, @PriceList

 

    COMMIT TRANSACTION

 

    RETURN 0

 

--存储过程二

 

CREATE PROCEDURE InsertOrderDetailsByList

 

    @Id        INT,

 

    @ProductIDList     NVARCHAR(4000) = NULL,

 

    @NumList      NVARCHAR(4000) = NULL,

 

    @PriceList      NVARCHAR(4000) = NULL

 

AS

 

    SET NOCOUNT ON

 

    DECLARE @Length INT

 

    DECLARE @FirstProductIdWord NVARCHAR(4000)

 

    DECLARE @FirstNumWord NVARCHAR(4000)

 

    DECLARE @FirstPriceWord NVARCHAR(4000)

 

    DECLARE @ProductId INT

 

    DECLARE @Num INT

 

    DECLARE @Price MONEY

 

    SELECT @Length = DATALENGTH(@ProductIDList)

 

    WHILE @Length > 0

 

    BEGIN

 

        EXECUTE @Length = PopFirstWord @@ProductIDList OUTPUT, @FirstProductIdWord OUTPUT

 

        EXECUTE PopFirstWord @NumList OUTPUT, @FirstNumWord OUTPUT

 

        EXECUTE PopFirstWord @PriceList OUTPUT, @FirstPriceWord OUTPUT

 

        IF @Length > 0

 

        BEGIN

 

            SELECT @ProductId = CONVERT(INT, @FirstProductIdWord)

 

            SELECT @Num = CONVERT(INT, @FirstNumWord)

 

            SELECT @Price = CONVERT(MONEY, @FirstPriceWord)

 

            EXECUTE InsertOrderDetail @Id, @ProductId, @Price, @Num

 

        END

 

    END

 

--存储过程三

 

CREATE PROCEDURE PopFirstWord

 

    @SourceString   NVARCHAR(4000) = NULL OUTPUT,

 

    @FirstWord      NVARCHAR(4000) = NULL OUTPUT

 

AS

 

    SET NOCOUNT ON

 

    DECLARE @Oldword        NVARCHAR(4000)

 

    DECLARE @Length         INT

 

    DECLARE @CommaLocation  INT

 

    SELECT @Oldword = @SourceString

 

    IF NOT @Oldword IS NULL

 

    BEGIN

 

        SELECT @CommaLocation = CHARINDEX(',',@Oldword)

 

        SELECT @Length = DATALENGTH(@Oldword)

 

        IF @CommaLocation = 0

 

        BEGIN

 

            SELECT @FirstWord = @Oldword

 

            SELECT @SourceString = NULL

 

            RETURN @Length

 

        END

 

        SELECT @FirstWord = SUBSTRING(@Oldword, 1, @CommaLocation -1)

 

        SELECT @SourceString = SUBSTRING(@Oldword, @CommaLocation + 1, @Length - @CommaLocation)

 

        RETURN @Length - @CommaLocation

 

    END

 

    RETURN 0

 

------------------------------------------------

 

--存储过程四

 

CREATE PROCEDURE InsertOrderDetail

    @OrderId    INT = NULL,

    @ProductId     INT = NULL,

    @Price  MONEY = NULL,

 

    @Num   INT = NULL

AS

    SET NOCOUNT ON

    INSERT OrderDetail(OrderId,ProductId,Price,Num)

    SELECT @OrderId,@ProductId,@Price,@Num

   RETURN 0

插入时,传入的子表数据都是长度为4000的NVARCHAR类型,各个字段使用“,”分割,然后调用PopFirstWord分拆后分别调用InsertOrderDetail进行保存,因为在InsertOrder中进行了事务处理,数据的安全性也比较有保障,几个存储过程设计的精巧别致,很有意思,但是子表的几个数据大小不能超过4000字符,恐怕不大保险。

第二种方法是我比较常用的,为了方便,就不用存储过程了,这个例子用的是VB.NET。

‘处理数据的类

 

Public class DbTools

 

    private Const _IDENTITY_SQL As String = "SELECT @@IDENTITY AS ID"

 

    private Const _ID_FOR_REPLACE As String = "_ID_FOR_REPLACE"

 

   ‘对主子表插入记录

 

   Public Function InsFatherSonRec(ByVal main_sql As String, ByVal ParamArray arParam() As String) As Integer

 

        Dim conn As New SqlConnection(StrConn)

 

       Dim ID AS INTEGER

 

        conn.Open()

 

        Dim trans As SqlTransaction = conn.BeginTransaction

 

        Try

 

            '主记录

 

            myDBTools.SqlData.ExecuteNonQuery(trans, CommandType.Text, main_sql)

 

            '返回新增ID号

 

            ID = myDBTools.SqlData.ExecuteScalar(trans, CommandType.Text, _IDENTITY_SQL)

 

            '从记录

 

            If Not arParam Is Nothing Then

 

                For Each sql In arParam

 

                    '将刚获得的ID号代入

 

                    sql = sql.Replace(_ID_FOR_REPLACE, ID)

 

                    myDBTools.SqlData.ExecuteNonQuery(trans, CommandType.Text, sql)

 

                Next

 

            End If

 

            trans.Commit()

 

            Catch e As Exception

 

                  trans.Rollback()

 

            Finally

 

            conn.Close()

 

        End Try

 

        Return ID

 

    End Function

 

End class

 

上面这段代码里有myDBTools,是对常见的数据库操作封装后的类,这个类对数据库进行直接的操作,有经验的.NET数据库程序员基本上都会有,一些著名的例子程序一般也都提供。

 

上面的是通用部分,下面是对具体单据的操作

 

Publid class Order

 

    Public _OrderDate as date            ‘主表记录

 

    Public ChildDt as datatable           ‘子表记录,结构与OrderDetail一致

 

    Public function Save() as integer

 

         Dim str as string

 

         Dim i as integer

 

         Dim arParam() As String

 

         Dim str as string=”insert into Order(OrderDate) values(‘” & _OrderDate & “’)”

 

        If not Childdt is nothing then

             arParam = New String(ChildDT.Rows.Count - 1) {}

             for i=0 to Childdt.rows.count-1

                 arparam(i)= ”insert into OrderDetail(OrderID,ProductID,Num,Price) Values(_ID_FOR_REPLACE,” & drow(“ProductID) & “,” & drow(“Num”) & “,” drow(“price”) & “)”

 

          next i

        End if

        Return (new dbtools). InsFatherSonRec(str,arparam)

End class


上面的两个例子为了方便解释,去掉了一些检验验证过程,有兴趣的朋友可以参照网上书店的例子研究第一种方法,或者根据自己的需要对第二种方法进行修改。


上一篇:sqlserver MSDTC的设置要点 人气:12430
下一篇:使用SQLSERVER的扩展存储过程实现远程备份与恢复 人气:10108
点击此处浏览全部sql server的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-5-16 乘风多用户PHP统计系统 v3.4
2008-5-16 轩溪下载系统 v3.78 build 0515
2008-5-16 普沙B2B 浙江省商贸网 v2.0
2008-5-16 asp抓蜘蛛的小程序 v1.0
2008-5-16 齐齐乐网私服发布站 仿haosf新版
2008-5-16 IssTech信息反馈系统 v1.0
2008-5-16 自由领域大头贴(js接口版) 修正版
2008-5-16 医院网站系统
2008-5-16 智拓-分类信息管理系统 v5.0
2008-5-7 Windows XP SP3 官方英文版
2008-5-7 Windows XP SP3 官方香港中文版
2008-5-7 Windows XP SP3 官方繁体中文版
2008-5-7 Windows XP SP3 官方简体中文版
2008-4-30 Multiple Unzip Wizard 1.02
2008-4-30 Multiple Unrar Wizard 1.0.0
2008-4-30 WinZip Install/Try/Uninstall a
2008-4-30 ZIP压缩文件修复器WzipFix 2.0
2008-4-30 Pentazip 6.01 Build 189 For Wi
  发表评论
姓 名: 验证码: [ 全部贴吧 ] [ 浏览评论 ]
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報