sqlserver中操作主從關(guān)系表的sql語句
更新時間:2011年07月20日 23:03:35 作者:
在項目開發(fā)中,經(jīng)常出現(xiàn)這樣的需求。在新增或修改一個主表數(shù)據(jù)時,對應(yīng)的從表也要進(jìn)行同步,此時我們是怎么操作的了?
典型的方法就是對于主表的各數(shù)據(jù)字段進(jìn)行更新或新增,對于從表一般都會先刪除相關(guān)的所有記錄,然后再進(jìn)行插入。也就是說每次保存時,從表的數(shù)據(jù)都要重新執(zhí)行一遍刪除再插入的過程。這是一個不錯的方法,在使用數(shù)據(jù)庫事務(wù)后,不會存在刪除后又沒有插入導(dǎo)致數(shù)據(jù)不一致的情況。
ok,原理是這樣,那么到實際的操作中,大家如何操作的呢?有人通過在程序中,通過多次數(shù)據(jù)庫操作完成如上的要求,這種方法可能存在這數(shù)據(jù)的不一致性,因為無法保證在兩個數(shù)據(jù)語句操作之間出現(xiàn)意外。那么我們就合并到一個存儲過程中去完成吧,復(fù)雜的參數(shù)和接收后處理,讓這個存儲過程變的困難。下邊我就結(jié)合實際應(yīng)用說說此過程吧。應(yīng)用場景,在學(xué)生管理中,添加一條學(xué)生記錄,對應(yīng)的要 添加學(xué)生對應(yīng)的課程。即每次更新和新增學(xué)生記錄,對應(yīng)其課程也要跟著變化。
那么這個過程,就符合上邊的邏輯。
通用的參數(shù)傳遞,在此不再詳說,重點講解,科目信息傳遞過后怎么處理。假設(shè)從表Tb_StudentSubject 存在StudentId,SubjectId兩個字段。那么代碼如下:
Create proc SaveInfo
(
---參數(shù)列表不再逐一書寫
@subjectList varchar(400))
as
begin tran
--新增或修改主表 省略
DECLARE @subjectID int,
@subjectIDsLen int,--科目長度
@subjectIDLen int,--單個科目長度
@nStart INT , -- 記錄查找的起始位置
@nLast INT -- 記錄‘,'的位置
select @subjectIDsLen=len(@SubjectIDs),@nStart=1,@nLast=0
DELETE Tb_StudentSubject WHERE StudentId=@sId --刪除相關(guān)的全部記錄
IF(@subjectIDsLen>0)
BEGIN
while(@nStart<@subjectIDsLen)
BEGIN
set @nLast=charindex(',',@SubjectIDs,@nStart)--從第@nStart個位置開始記錄逗號的位置
set @subjectIDLen=@nLast-@nStart --記錄每個subjectID的長度
set @subjectID=substring(@SubjectIDs,@nStart,@subjectIDLen)--獲取一個subjectID
Insert Into Tb_StudentSubject(StudentId,SubjectID)values(@sId,@subjectID)
set @nStart=@nLast+1--設(shè)置下次查找的起始位置
END
END
if @@Error=0
commit transaction
else
rollback transaction
End
在這邊代碼中,科目列表通過“,”進(jìn)行分割,上邊的存儲過程帶注釋,重點說明兩個系統(tǒng)自帶的函數(shù)
CHARINDEX ( expression1 ,expression2 [ , start_location ] )
expression1 :其中包含要查找的字符的序列
expression2 :通常是一個為指定序列搜索的列
start_location :開始在 expression2 中搜索 expression1 時的字符位置。如果 start_location 未被指定、是一個負(fù)數(shù)或零
另一個函數(shù)就是:SUBSTRING ( expression ,start , length )從指定的數(shù)據(jù)源串中從指定位置截取指定長度的串
其中 expression :是字符串、二進(jìn)制字符串,要操作的數(shù)據(jù)源串
start:要截取的開始位置,注意此方法和C#自帶的位置不一樣,數(shù)據(jù)庫中strat從1開始,程序中從0開始
length:截取內(nèi)容的長度
另外一個就len(expres) 這個就比較簡單了,獲取指定字符的長度
通過以上代碼,就可以實現(xiàn)一個完整存儲過程實現(xiàn)主從表數(shù)據(jù)的處理了,在數(shù)據(jù)一致性和操作便捷性得到保證,而且相同通用。
注:在涉及類似主從關(guān)系表中,建議不要在從表中設(shè)置自動編號的主鍵,因為頻繁的刪除和添加,導(dǎo)致主鍵不斷的累增,而且毫無使用此主鍵的意義。
以上內(nèi)容是個人見解,希望大家多交流相應(yīng)的方法。
ok,原理是這樣,那么到實際的操作中,大家如何操作的呢?有人通過在程序中,通過多次數(shù)據(jù)庫操作完成如上的要求,這種方法可能存在這數(shù)據(jù)的不一致性,因為無法保證在兩個數(shù)據(jù)語句操作之間出現(xiàn)意外。那么我們就合并到一個存儲過程中去完成吧,復(fù)雜的參數(shù)和接收后處理,讓這個存儲過程變的困難。下邊我就結(jié)合實際應(yīng)用說說此過程吧。應(yīng)用場景,在學(xué)生管理中,添加一條學(xué)生記錄,對應(yīng)的要 添加學(xué)生對應(yīng)的課程。即每次更新和新增學(xué)生記錄,對應(yīng)其課程也要跟著變化。
那么這個過程,就符合上邊的邏輯。
通用的參數(shù)傳遞,在此不再詳說,重點講解,科目信息傳遞過后怎么處理。假設(shè)從表Tb_StudentSubject 存在StudentId,SubjectId兩個字段。那么代碼如下:
復(fù)制代碼 代碼如下:
Create proc SaveInfo
(
---參數(shù)列表不再逐一書寫
@subjectList varchar(400))
as
begin tran
--新增或修改主表 省略
DECLARE @subjectID int,
@subjectIDsLen int,--科目長度
@subjectIDLen int,--單個科目長度
@nStart INT , -- 記錄查找的起始位置
@nLast INT -- 記錄‘,'的位置
select @subjectIDsLen=len(@SubjectIDs),@nStart=1,@nLast=0
DELETE Tb_StudentSubject WHERE StudentId=@sId --刪除相關(guān)的全部記錄
IF(@subjectIDsLen>0)
BEGIN
while(@nStart<@subjectIDsLen)
BEGIN
set @nLast=charindex(',',@SubjectIDs,@nStart)--從第@nStart個位置開始記錄逗號的位置
set @subjectIDLen=@nLast-@nStart --記錄每個subjectID的長度
set @subjectID=substring(@SubjectIDs,@nStart,@subjectIDLen)--獲取一個subjectID
Insert Into Tb_StudentSubject(StudentId,SubjectID)values(@sId,@subjectID)
set @nStart=@nLast+1--設(shè)置下次查找的起始位置
END
END
if @@Error=0
commit transaction
else
rollback transaction
End
在這邊代碼中,科目列表通過“,”進(jìn)行分割,上邊的存儲過程帶注釋,重點說明兩個系統(tǒng)自帶的函數(shù)
CHARINDEX ( expression1 ,expression2 [ , start_location ] )
expression1 :其中包含要查找的字符的序列
expression2 :通常是一個為指定序列搜索的列
start_location :開始在 expression2 中搜索 expression1 時的字符位置。如果 start_location 未被指定、是一個負(fù)數(shù)或零
另一個函數(shù)就是:SUBSTRING ( expression ,start , length )從指定的數(shù)據(jù)源串中從指定位置截取指定長度的串
其中 expression :是字符串、二進(jìn)制字符串,要操作的數(shù)據(jù)源串
start:要截取的開始位置,注意此方法和C#自帶的位置不一樣,數(shù)據(jù)庫中strat從1開始,程序中從0開始
length:截取內(nèi)容的長度
另外一個就len(expres) 這個就比較簡單了,獲取指定字符的長度
通過以上代碼,就可以實現(xiàn)一個完整存儲過程實現(xiàn)主從表數(shù)據(jù)的處理了,在數(shù)據(jù)一致性和操作便捷性得到保證,而且相同通用。
注:在涉及類似主從關(guān)系表中,建議不要在從表中設(shè)置自動編號的主鍵,因為頻繁的刪除和添加,導(dǎo)致主鍵不斷的累增,而且毫無使用此主鍵的意義。
以上內(nèi)容是個人見解,希望大家多交流相應(yīng)的方法。
相關(guān)文章
sqlserver 文件數(shù)據(jù)庫和關(guān)系數(shù)據(jù)庫的比較
本文概要地從數(shù)據(jù)格式、數(shù)據(jù)庫結(jié)構(gòu)和WEB發(fā)布數(shù)據(jù)三個方面比較了文件數(shù)據(jù)庫和關(guān)系數(shù)據(jù)庫的異同,同時差別了文件數(shù)據(jù)庫和過去存儲數(shù)據(jù)的文件系統(tǒng)的不同2011-10-10SQL參數(shù)化查詢的另一個理由 命中執(zhí)行計劃
為了提高數(shù)據(jù)庫運行的效率,我們需要盡可能的命中執(zhí)行計劃,這樣就可以節(jié)省運行時間2012-08-08SQL Server游標(biāo)的使用/關(guān)閉/釋放/優(yōu)化小結(jié)
游標(biāo)打破了這一查詢的思考是面向集合的規(guī)則,游標(biāo)使得我們思考方式變?yōu)橹鹦羞M(jìn)行,接下來為大家介紹下游標(biāo)的使用感興趣的朋友可以參考下哈,希望可以幫助到你2013-03-03快速插入大量數(shù)據(jù)的asp.net代碼(Sqlserver)
目標(biāo)數(shù)據(jù)庫只能是Sqlserver 來源數(shù)據(jù)庫 無所謂 只要能用ado.net 將來源數(shù)據(jù)讀取到Dataset或者Datareader 中就可以了。2011-02-02SQL語句中的DDL類型的數(shù)據(jù)庫定義語言操作
這篇文章主要介紹了SQL語句中的DDL類型的數(shù)據(jù)庫定義語言,主要是用來定義數(shù)據(jù)庫中的對象的,例如數(shù)據(jù)庫、表和字段的定義,簡單的理解就是DDL語言是來操作數(shù)據(jù)庫、表和字段的,需要的朋友可以參考下2022-08-08如何恢復(fù)SQL Server 2000損壞的數(shù)據(jù)庫文件
在現(xiàn)實情況中由于硬件和軟件的原因可能導(dǎo)致數(shù)據(jù)庫文件損壞,那么損壞的數(shù)據(jù)庫文件有沒有辦法修復(fù)呢?下面講講如何恢復(fù)SQL Server 2000損壞的數(shù)據(jù)庫文件2014-01-01SQLServer 2005 實現(xiàn)數(shù)據(jù)庫同步備份 過程-結(jié)果-分析
簡單來說,數(shù)據(jù)庫復(fù)制就是由兩臺服務(wù)器,主服務(wù)器和備份服務(wù)器,主服務(wù)器修改后,備份服務(wù)器自動修改2012-06-06