最近sql數據庫的使用總結

Sql學習

 

 

•1、             帶遊標的存儲過程:

存儲過程的定義規範,我們可以參照sql的聯機幫助,可以詳細的得到。

CREATE PROCEDURE copyData AS

declare @qid int,

    @orgAddr varchar(25),

       @destaddr varchar(25),

       @answers varchar(256),

       @receivedate datetime,

       @serviceID varchar(10)

DECLARE MutiInsert_Cursor CURSOR FOR

select substring(DestAddr,14,17) as QID,OrgAddr,DestAddr,SM_Content,RecvTime,ServiceID from tbl_SMReceived

where Reserve2 is NULL

 

OPEN MutiInsert_Cursor

 

FETCH NEXT FROM MutiInsert_Cursor

into @qid,@orgAddr,@destaddr,@answers,@receivedate,@serviceID

WHILE @@FETCH_STATUS = 0

BEGIN

    insert into tbl_Answers (QID,OrgAddr,DestAddr,Anwsers,ReceiveDate,ServiceID)

       values(@qid,@orgAddr,@destaddr,','+@answers+',',@receivedate,@serviceID)

    FETCH NEXT FROM MutiInsert_Cursor

    into @qid,@orgAddr,@destaddr,@answers,@receivedate,@serviceID

END

CLOSE MutiInsert_Cursor

DEALLOCATE MutiInsert_Cursor

GO

上述存儲過程用了遊標,在使用存儲過程時可能會出現查出多條記錄插入一個表中的情況,當出現這種情況的時候sql會報錯,錯誤大致意思就是不能同時插入處理多行。這個時候遊標的作用就凸現出來啦。

遊標顧名思義就像一個可以遊動的指針,它指向結果的"一條"記錄,這個一條很重要,這樣就可以有了解決多行處理的方法。

定義方法:DECLARE MutiInsert_Cursor CURSOR FOR ........

For後的內容就是一張表,可以使select語句查詢出來的表,也可以是其他。

在看後面的代碼,你會發現,這跟asp讀取數據庫的recordset很相似,應該就是一個東西吧,遊標嘛。

定義好遊標後,先打開它,這時就可以讀出它這個時候指向的記錄內容。讀取方法爲:

FETCH NEXT FROM MutiInsert_Cursor

into @qid,@orgAddr,@destaddr,@answers,@receivedate,@serviceID

into後面的東西就是存儲過程一開始定義的變量。

對於內容遍歷,可以做一個循環(如下:):

WHILE @@FETCH_STATUS = 0

BEGIN

    insert into tbl_Answers (QID,OrgAddr,DestAddr,Anwsers,ReceiveDate,ServiceID)

       values(@qid,@orgAddr,@destaddr,','+@answers+',',@receivedate,@serviceID)

    FETCH NEXT FROM MutiInsert_Cursor

    into @qid,@orgAddr,@destaddr,@answers,@receivedate,@serviceID

END

完成所有之後記住要關閉遊標,釋放之。

•2、             自定義函數

自定義的函數可以減少很多工作量,是我們編程者京城用到的,在sql中也一樣不例外。

 

打開上圖中的內容,即爲該數據庫中存在的用戶自定義函數。

簡單語法

CREATE FUNCTION [ owner_name.] function_name
    ( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] } [ ,...n ] ] )

RETURNS scalar_return_data_type

[ WITH < function_option> [ [,] ...n] ]

[ AS ]

BEGIN
    function_body
    RETURN scalar_expression
END

owner_name

擁有該用戶定義函數的用戶 ID 的名稱。owner_name 必須是現有的用戶 ID。

function_name

用戶定義函數的名稱。函數名稱必須符合標識符的規則,對其所有者來說,該名稱在數據庫中必須是唯一的。

@parameter_name

用戶定義函數的參數。CREATE FUNCTION 語句中可以聲明一個或多個參數。函數最多可以有 1,024 個參數。函數執行時每個已聲明參數的值必須由用戶指定,除非該參數的默認值已經定義。 如果函數的參數有默認值,在調用該函數時必須指定"default"關鍵字才能獲得默認值。這種行爲不同於存儲過程中有默認值的參數,在存儲過程中省略參數也意味着使用默認值。

使用 @ 符號作爲第一個字符來指定參數名稱。參數名稱必須符合標識符的規則。每個函數的參數僅用於該函數本身;相同的參數名稱可以用在其它函數中。參數只能代替常量;而不能用於代替表名、列名或其它數據庫對象的名稱。

scalar_parameter_data_type

參數的數據類型。所有標量數據類型(包括 bigintsql_variant)都可用作用戶定義函數的參數。不支持 timestamp 數據類型和用戶定義數據類型。不能指定非標量類型(例如 cursor 和 table)。

scalar_return_data_type

是標量用戶定義函數的返回值。scalar_return_data_type 可以是 SQL Server 支持的任何標量數據類型(textntextimage timestamp 除外)。

scalar_expression

指定標量函數返回的標量值。

TABLE

指定表值函數的返回值爲表。

在內嵌表值函數中,通過單個 SELECT 語句定義 TABLE 返回值。內嵌函數沒有相關聯的返回變量。

在多語句表值函數中,@return_variable 是 TABLE 變量,用於存儲和累積應作爲函數值返回的行。

function_body

指定一系列 Transact-SQL 語句定義函數的值,這些語句合在一起不會產生副作用。function_body 只用於標量函數和多語句表值函數。

在標量函數中,function_body 是一系列合起來求得標量值的 Transact-SQL 語句。

詳見sql的聯機幫助!!!

 

 

一下介紹一個函數使用例子:

此例子的功能是判斷輸入字符串中是否含有數字和逗號之外的字符,有就返回0,沒有就返回1:

CREATE  FUNCTION PanDuan  (@PanduanStr as varchar(200)) 

RETURNS int  AS 

BEGIN

declare @ComPare varchar(100)

declare @index int

set @index=1

set @ComPare='1,2,3,4,5,6,7,8,9,0'

while(@index<=len(@PanduanStr))

BEGIN

if(CHARINDEX(substring(@PanduanStr,@index,1),@ComPare,1)=0)

begin

return 0

end

set @index=@index+1

END

return 1

END

上述的函數對字符串做了一個遍歷,使用substring和循環獲取字符串中的單個字符,使用charindex判斷字符串是否符合要求。

 

函數的調用:

函數的調用方法規範爲:數據庫名稱.dbo.函數名稱(參數)

注意同一數據庫中的數據庫名稱可以省略,但是dbo不可省略。不加dbo,系統會認爲函數是系統函數而非用戶自定義函數。

•3、             定義作業

作業也是sql的又一重要的功能,使用者可以將週期執行的過程讓作業來完成,定義作業的方法爲如下:

 

上圖就是作業定義的位置,在上面右鍵就可以新建作業,出現新建作業對話框,然後按照要求一步一步的就可以完成作業的定義:

 

步驟的定義:

步驟就是這個作業的具體內容,可以定義多個步驟,步驟中的內容就是sql語句,其可以exec存儲過程等等。

 

 

調度的設置:調度中可以設置作業的執行週期等。一般可以設置的最短時間間隔是一分鐘,但是我們可以定義多個調度來彼此之間設定一定得執行間隔來完成更短時間的間隔。比如你想每半分鐘執行一次作業,那麼你就可以定義兩個調度,二者之間執行的時間間隔設成30秒,這個時候就可以構成30秒執行一次的作業。

 

 

•4、             觸發器編寫

觸發器在簡化前臺程序的時候顯得非常有用。常常用來處理很多插入刪除更新的操作。

觸發器,顧名思義就是觸發的樞紐,比如插入,刪除,更新記錄的時候就會使這個樞紐啓動起來,這個樞紐也是很多sql語句。

在插入觸發器中常使用的一個inserted,其意思就是當前插入的這行記錄。

注意:觸發器有三種類型:

  • AFTER 觸發器在觸發操作(INSERT、UPDATE 或 DELETE)後和處理完任何約束後激發。可通過指定 AFTER 或 FOR 關鍵字來請求 AFTER 觸發器。因爲 FOR 關鍵字與 AFTER 的效果相同,所以具有 FOR 關鍵字的觸發器也歸類爲 AFTER 觸發器。
  • INSTEAD OF 觸發器代替觸發動作進行激發,並在處理約束之前激發。

對於每個觸發操作(UPDATE、DELETE 和 INSERT),每個表或視圖只能有一個 INSTEAD OF 觸發器。而一個表對於每個觸發操作可以有多個 AFTER 觸發器。

示例
A. 用 INSTEAD OF 觸發器代替標準觸發動作
CREATE TRIGGER TableAInsertTrig ON TableA
INSTEAD OF INSERT
AS ...
B. 用 AFTER 觸發器增加標準觸發動作
CREATE TRIGGER TableBDeleteTrig ON TableB
AFTER DELETE
AS ...
C. 用 FOR 觸發器增加標準觸發動作
-- This statement uses the FOR keyword to generate an AFTER trigger.
CREATE TRIGGER TableCUpdateTrig ON TableC
FOR UPDATE
AS ...

 

for觸發器是在操作的動作完成後才觸發的,比如:插入觸發器,其執行是在插入進去了一條記錄才執行,而非插入這一動作觸發,等觸發器完成後在插入記錄,也就是說,執行觸發器內容是所屬表已經做了更新,這一點很重要。

一個觸發器的例子,很長,沒做簡化,以顯示觸發器的重要性,其中也有很多有用的sql語句以備以後使用。

CREATE TRIGGER [triAnswers] ON [dbo].[tbl_Answers]

FOR INSERT

AS

if ((select OrgAddr from inserted) not  in (select memberMobile from tbl_Member))

BEGIN

insert into tbl_SMSendTask (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS','對不起,沒有你的信息,無法進行投票',DestAddr,OrgAddr,'4','0','01','0','0'from inserted

update tbl_Answers set Useable=0 where id=(select id from inserted)

END

else

if((select OrgAddr from inserted) not in (

select memberMobile from tbl_GroupMemberRelation where groupid=(select

groupid from tbl_title where id=(select titleid from tbl_option where id=(select id from

tbl_middle where QID=(select qid from inserted))))))

BEGIN

insert into tbl_SMSendTask  (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS','對不起,你不是該小區的業主,無權進行投票',DestAddr,OrgAddr,'4','0','01','0','0' from inserted

update tbl_Answers set Useable=0 where id=(select id from inserted)

END

else

if(EXISTS

    (

             select qid from inserted,(

         select [id],enddate from tbl_Title

         ) b where b.[id]=(select titleid from tbl_option where id=(select id from tbl_middle where QID=(select qid from inserted))) and receivedate>enddate

    )

 )

BEGIN

insert into tbl_SMSendTask  (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS', '對不起,該投票已結束',DestAddr,OrgAddr,'4','0','01','0','0'from inserted

update tbl_Answers set Useable=0 where id=(select id from inserted)

END

else

if(((select count(QID) from tbl_Answers where OrgAddr=(select OrgAddr from inserted) and qid=(select qid from inserted) and useable=1)>1) )

BEGIN

insert into tbl_SMSendTask  (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS', '對不起,該項議題您已經投過票了,請不要重複投票',inserted.DestAddr,inserted.OrgAddr,'4','0','01','0','0' from inserted

update tbl_Answers set Useable=0 where id=(select id from inserted)

END

else

if(EXISTS

(

 select Option_Type from tbl_option

 where id=(select id from tbl_middle where QID=(select qid from inserted)) and Option_Type<9

) and dbo.PanDuan((select Anwsers from inserted))=0

)

BEGIN

insert into tbl_SMSendTask  (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS', '對不起,投票失敗,單選或多選請不要出現逗號和數字之外的字符!',inserted.DestAddr,inserted.OrgAddr,'4','0','01','0','0' from inserted

update tbl_Answers set Useable=0 where id=(select id from inserted)

END

else

BEGIN

Insert into tbl_SMSendTask  (CreatorID,ServiceID,OperationType,sm_Content,OrgAddr,DestAddr,SendType,TaskStatus,FeeType,FeeCode,MsgID)

select '0000',ServiceID,'WAS', '恭喜您,投票成功,謝謝參與!',inserted.DestAddr,inserted.OrgAddr,'4','0','01','0','0' from inserted

END

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