用觸發器解決sqlserver導入數據與表衝突問題

如果新建的表中某一列屬性有約束,那麼在sqlserver中導入數據過程中,如果有不符合該約束的值,就會導致衝突,導入失敗。
一般的做法是先導入一個沒有約束的表,然後在sqlserver中通過查詢語句篩選掉不符合約束條件的元組,然後insert進入有約束的表。
顯然這種方式簡單但是會損耗空間,並且如果導入的數據表如果很多,這樣的操作會很繁瑣。
下面介紹用觸發器解決這一問題的方式:

先建表

create table student(
number nchar(8) not null,
name varchar(50) not null,
sex nchar(2) not null check(sex in ('男','女')),
age int not null,
class int not null,
score decimal(5,2) check(score>=0 and score <=10),
time  varchar(50)
)

這裏爲score屬性添加了約束

創建觸發器

sqlserver的觸發器沒有before語法,所以只能通過重寫insert來解決,如果數據庫是mysql可以用before,會方便很多

Create Trigger scorecheck
  ON student
  Instead Of Insert			//創建觸發器的基本語句
AS
Begin
    Set Nocount On;			//這裏開始建立虛表
    Declare @number nchar(8),
	@name varchar(50),
    @sex nchar(2),
    @age int,
    @class int,
    @score decimal(5,2),
    @time  varchar(50)
    DECLARE YB CURSOR FOR
    SELECT [number],[name],[sex],[age],[class],[score],[time] FROM INSERTED				//inserted是sqlserver中自帶的參數,表示導入的表
    OPEN YB //打開導入的虛表
    FETCH NEXT FROM YB INTO	 @number,@name,@sex,@age,@class,@score,@time
    //獲取第一行的元組
	WHILE @@FETCH_STATUS = 0	//由於表有很多元組,我們需要遍歷每一行
	//這裏相當於while hasnextline
	begin
    if(@score)<0 or (@score)>10	//篩選
    begin
       print '分數不合法'
    end
    else
    begin
       insert into student(number,name,sex,age,class,score,time) values(@number,@name,@sex,@age,@class,@score,@time)
       //符合條件的元組插入表中
    end
	FETCH NEXT FROM YB INTO @number,@name,@sex,@age,@class,@score,@time
	//獲取下一行
	END
	CLOSE YB
	DEALLOCATE YB
End

導入數據

sqlserver自帶的導入數據程序是不經過我們創建的觸發器的,就是我們不能通過 任務->導入文件 來導入數據
我們只能手寫導入文件
通過bulk insert導入文件,這邊文件類型是csv,所以分隔符是,和\n,不同的文件類型有不同的分隔符。
此外,一般數據庫都設有權限,你可能沒有權限導入放在桌面或其他文件夾的文件,解決方法是把該文件放在C盤

bulk insert student
from 'C:\student.csv'	//C盤的csv文件
with(
    FIELDTERMINATOR=',',
    ROWTERMINATOR='\n' ,
    FIRSTROW=2,
	FIRE_TRIGGERS	//這行的意思是導入過程經過所有觸發器
)

到這裏就可以了,不合法的數據會被篩選掉不導入,並且有數據不合法的提示。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章