SQL
1.觸發器TRIGGER
兩個臨時表:Deleted Inserted
虚拟表Inserted 虚拟表Deleted
在表记录新增时 存放新增的记录 不存储记录
修改时 存放用来更新的新记录 存放更新前的记录
删除时 不存储记录 存放被删除的记录
修改記錄
USE [TECOSFIS] GO /****** Object: Trigger [dbo].[TestTecoSfis] Script Date: 06/13/2012 14:55:42 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: <Author,,Name> -- Create date: <Create Date,,> -- Description: <Description,,> -- ============================================= ALTER TRIGGER [dbo].[TestTecoSfis] ON [dbo].[BOM] AFTER Update AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; if Update(BOMCode) begin Update dbo.Table_1 set barcode=i.BOMCode from Table_1 br,Deleted d ,Inserted i Where br.barcode=d.BOMCode end -- Insert statements for trigger here END
新增記錄
ALTER TRIGGER [dbo].[TestTecoSfis] ON [dbo].[BOM] AFTER insert AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; insert into dbo.Table_1( barcode,bedate) select BOMCode,getdate() from Inserted i -- Insert statements for trigger here END
刪除記錄
ALTER TRIGGER [dbo].[TestTecoSfis] ON [dbo].[BOM] AFTER delete AS BEGIN SET NOCOUNT ON; delete dbo.Table_1 from Table_1 m,deleted i where m.barcode=i.BOMCode END
2.存儲過程 PROCEDURE
2.1 定義參數 定義變量
@pDocID VARCHAR(4),前面是參數名,後面是變量類型。
下面是存儲過程中用到的變量的定義
DECLARE @SysDate DATETIME
DECLARE @Seq DECIMAL(4, 0)
2.2 定義賦值
SET @oMsgNo = ''用set語句
2.3 在存儲過程中執行sql
EXEC( @SqlCountStmt )
2.4 在存儲過程中推薦使用公用表表达式(CTE),比臨時表快的多。
EXEC( '
WITH TempTCE AS (' + @SqlStmt + ')
SELECT *
FROM TempTCE
WHERE RowNumber BETWEEN ' + @strStartRowNumber + ' AND '+ @strEndRowNumber + '
'
分頁存儲過程
USE [Myufull] GO /****** Object: StoredProcedure [dbo].[sp_Paging_RowNumber] Script Date: 06/14/2012 14:28:39 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[sp_Paging_RowNumber] @SqlStmt nvarchar(max), @PageIndex int = 0, @PageSize int = 10, @SqlCountStmt nvarchar(max) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; /*Default Page Number*/ IF @PageIndex < 0 AND @PageSize < 0 BEGIN /*Execute dynamic query*/ EXEC( ' WITH TempTCE AS (' + @SqlStmt + ') SELECT * FROM TempTCE ' ) END ELSE BEGIN IF @PageIndex < 0 SET @PageIndex = 0 DECLARE @strStartRowNumber varchar(50) DECLARE @strEndRowNumber varchar(50) SET @strStartRowNumber = CAST( ((@PageIndex)*@PageSize+1) AS varchar(50)) SET @strEndRowNumber = CAST( (@PageIndex + 1)* @PageSize AS varchar(50)) /*Execute dynamic query*/ EXEC( ' WITH TempTCE AS (' + @SqlStmt + ') SELECT * FROM TempTCE WHERE RowNumber BETWEEN ' + @strStartRowNumber + ' AND '+ @strEndRowNumber + ' ' ) END EXEC( @SqlCountStmt ) END
庫存處理存儲過程:
USE [Myufull] GO /****** Object: StoredProcedure [dbo].[StockChange] Script Date: 06/14/2012 14:39:49 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[StockChange] -- Add the parameters for the stored procedure here @pDOC_NO VARCHAR (20), -- 單據編號 @pDOC_ID VARCHAR (4), -- 單據代號 @pBOOK_YM VARCHAR (6), -- 記帳年月 @pDOC_DATE DATETIME, -- 單據日期 @pDEPT_ID VARCHAR (10), -- 單位代號 @pDOC_SEQ DECIMAL (4,0), -- 單據項次 @pTYPE VARCHAR (2), -- 異動類型(系代MM030:I入、O出、IC入庫作廢、OC出庫作廢) @pWH_ID VARCHAR (10), -- 倉庫代號 @pITEM_CODE VARCHAR (20), -- 商品代號 @pQTY DECIMAL (8,2), -- 數量 @pSTOCK_AMT DECIMAL (12,2), -- 存貨金額 @pSALE_AMT DECIMAL (12,2), -- 銷售金額(含稅) @pMEMO NVARCHAR(255), -- 備註 @pBATCH_NUMBER VARCHAR (20), -- 批號 @pUSER_ID VARCHAR (10), -- 執行者帳號 @pUSER_NAME NVARCHAR(20), -- 執行者姓名 @oMSG_NO VARCHAR (6) OUTPUT -- 錯誤訊息代號 AS DECLARE @I_QTY DECIMAL(8, 2) DECLARE @I_STOCK_AMT DECIMAL(12, 2) DECLARE @O_QTY DECIMAL(8, 2) DECLARE @O_STOCK_AMT DECIMAL(12, 2) DECLARE @IC_QTY DECIMAL(8, 2) DECLARE @IC_STOCK_AMT DECIMAL(12, 2) DECLARE @OC_QTY DECIMAL(8, 2) DECLARE @OC_STOCK_AMT DECIMAL(12, 2) DECLARE @STOCK_QTY DECIMAL(8, 2) DECLARE @STOCK_QTY_T DECIMAL(8, 2) DECLARE @STOCK_AMT_NOW DECIMAL(12, 2) DECLARE @STOCK_AMT_NOW_T DECIMAL(12, 2) DECLARE @STOCK_AMT_DIFF DECIMAL(12, 2) SET @I_QTY = 0 SET @I_STOCK_AMT = 0 SET @O_QTY = 0 SET @O_STOCK_AMT = 0 SET @IC_QTY = 0 SET @IC_STOCK_AMT = 0 SET @OC_QTY = 0 SET @OC_STOCK_AMT = 0 SET @STOCK_QTY = 0 SET @STOCK_QTY_T = 0 SET @STOCK_AMT_NOW = 0 SET @STOCK_AMT_NOW_T = 0 SET @STOCK_AMT_DIFF = 0 BEGIN SET NOCOUNT ON; BEGIN -- INPUT CHECK -- 檢查傳入參數是否空白或不存在 IF ISNULL(@pDOC_NO, '') = '' SET @oMSG_NO = 'E20053' ELSE IF @pDOC_SEQ IS NULL SET @oMSG_NO = 'E20054' ELSE IF ISNULL(@pTYPE, '') = '' OR @pTYPE NOT IN (SELECT CODE_NO FROM SYS07M WHERE CLASS_NO = 'MM030') SET @oMSG_NO = 'E20055' ELSE IF ISNULL(@pWH_ID, '') = '' SET @oMSG_NO = 'E20056' ELSE IF ISNULL(@pDEPT_ID, '') = '' SET @oMSG_NO = 'E20072' ELSE IF ISNULL(@pITEM_CODE, '') = '' SET @oMSG_NO = 'E20057' ELSE IF @pQTY IS NULL OR @pQTY <= 0 SET @oMSG_NO = 'E20058' ELSE IF @pSTOCK_AMT IS NULL OR @pSTOCK_AMT < 0 SET @oMSG_NO = 'E20059' ELSE IF ISNULL(@pDOC_ID, '') = '' OR @pDOC_ID NOT IN (SELECT DOC_ID FROM SYS15M) SET @oMSG_NO = 'E20062' IF @oMSG_NO <> '' GOTO ERR -- 檢查傳入單位是否存在 SELECT * FROM SYS14M WHERE DEPT_ID = @pDEPT_ID IF @@ROWCOUNT = 0 BEGIN SET @oMSG_NO = 'E20073' GOTO ERR END -- 檢查傳入倉庫是否存在 SELECT * FROM MMA05M WHERE WH_ID = @pWH_ID AND DEPT_ID = @pDEPT_ID IF @@ROWCOUNT = 0 BEGIN SET @oMSG_NO = 'E20060' GOTO ERR END -- 檢查傳入商品代號是否存在 SELECT * FROM MMA01M WHERE ITEM_CODE = @pITEM_CODE IF @@ROWCOUNT = 0 BEGIN SET @oMSG_NO = 'E20061' GOTO ERR END -- 給定入出數量金額 IF @pTYPE = 'I' BEGIN SET @I_QTY = @pQTY SET @I_STOCK_AMT = @pSTOCK_AMT END ELSE IF @pTYPE = 'O' BEGIN SET @O_QTY = @pQTY SET @O_STOCK_AMT = @pSTOCK_AMT END ELSE IF @pTYPE = 'IC' BEGIN SET @IC_QTY = @pQTY SET @IC_STOCK_AMT = @pSTOCK_AMT END ELSE IF @pTYPE = 'OC' BEGIN SET @OC_QTY = @pQTY SET @OC_STOCK_AMT = @pSTOCK_AMT END ELSE BEGIN SET @oMSG_NO = 'E20055' GOTO ERR END -- 若為出庫或入出庫作廢,則檢查傳入倉庫之商品是否庫存足夠 IF @pTYPE IN ('O', 'IC', 'OC') BEGIN SELECT * FROM MMB01M WHERE ITEM_CODE = @pITEM_CODE AND WH_ID = @pWH_ID IF @@ROWCOUNT = 0 --沒有庫存紀錄卻執行出庫或入出庫作廢 BEGIN SET @oMSG_NO = 'E20070' GOTO ERR END ELSE BEGIN SELECT @STOCK_QTY = STOCK_QTY , @STOCK_AMT_NOW = STOCK_AMT FROM MMB01M WHERE ITEM_CODE = @pITEM_CODE AND WH_ID = @pWH_ID -- 計算庫存異動數量 IF @STOCK_QTY + @I_QTY - @O_QTY - @IC_QTY + @OC_QTY < 0 BEGIN SET @oMSG_NO = 'E20071' GOTO ERR END -- 若出庫存貨金額大於目前存貨金額 IF @STOCK_AMT_NOW - @O_STOCK_AMT < 0 BEGIN SET @oMSG_NO = 'E20094' GOTO ERR END END END -- 若進貨作廢存貨金額大於目前存貨金額 SELECT @STOCK_QTY_T = SUM(STOCK_QTY) , @STOCK_AMT_NOW_T = SUM(STOCK_AMT) FROM MMB01M WHERE ITEM_CODE = @pITEM_CODE IF @@ROWCOUNT = 0 IF @STOCK_AMT_NOW_T - @IC_STOCK_AMT < 0 BEGIN SET @STOCK_AMT_DIFF = @IC_STOCK_AMT - @STOCK_AMT_NOW_T SET @IC_STOCK_AMT = @STOCK_AMT_NOW_T END -- END END -- 更新庫存主檔(MMB01M) BEGIN TRY SELECT * FROM MMB01M WHERE ITEM_CODE = @pITEM_CODE AND WH_ID = @pWH_ID IF @@ROWCOUNT = 0 BEGIN INSERT INTO MMB01M (WH_ID ,ITEM_CODE ,STOCK_QTY ,STOCK_AMT ,INS_USER_ID ,INS_USER_NAME ,INS_DATE) VALUES (@pWH_ID ,@pITEM_CODE ,@I_QTY ,@pSTOCK_AMT ,@pUSER_ID ,@pUSER_NAME ,GETDATE()) END ELSE BEGIN UPDATE MMB01M SET STOCK_QTY = STOCK_QTY + @I_QTY - @O_QTY - @IC_QTY + @OC_QTY, STOCK_AMT = STOCK_AMT + @I_STOCK_AMT - @O_STOCK_AMT - @IC_STOCK_AMT + @OC_STOCK_AMT, UPD_USER_ID = @pUSER_ID, UPD_USER_NAME = @pUSER_NAME, UPD_DATE = GETDATE() WHERE ITEM_CODE = @pITEM_CODE AND WH_ID = @pWH_ID END END TRY BEGIN CATCH SET @oMSG_NO = 'E20064' GOTO ERR END CATCH BEGIN TRY INSERT INTO MMB02M (DOC_NO ,DOC_ID ,BOOK_YM ,DOC_DATE ,DEPT_ID ,DOC_SEQ ,TYPE ,WH_ID ,ITEM_CODE ,QTY ,STOCK_AMT ,STOCK_AMT_DIFF ,SALE_AMT ,MEMO ,BATCH_NUMBER ,INS_USER_ID, INS_USER_NAME, INS_DATE) VALUES (@pDOC_NO ,@pDOC_ID ,@pBOOK_YM ,@pDOC_DATE ,@pDEPT_ID ,@pDOC_SEQ ,@pTYPE ,@pWH_ID ,@pITEM_CODE ,@pQTY ,@pSTOCK_AMT ,@STOCK_AMT_DIFF ,@pSALE_AMT ,@pMEMO ,@pBATCH_NUMBER ,@pUSER_ID, @pUSER_NAME, GETDATE()) END TRY BEGIN CATCH SET @oMSG_NO = 'E20063' GOTO ERR END CATCH ERR: RETURN -1 END
2.5 生成臨時表 #accountinfo_up
select a.* into #accountinfo_up from ocsweb.dbo.accountinfo a
2.6 遊標
游标允许应用程序对查询语句select 返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;它还提供对基于游标位置而对表中数据进行删除或更新的能力;而且, 正是游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。
使用遊標的注意事項:
使用游标时应注意的问题:
(1) 尽管使用游标比较灵活,可以实现对数据集中单行数据的直接操作,但游标会在下面几个方面影响系统的性能:
-使用游标会导致页锁与表锁的增加
-导致网络通信量的增加
-增加了服务器处理相应指令的额外开销
(2) 使用游标时的优化问题:
-明确指出游标的用途:for read only或for update
-在for update后指定被修改的列
2.6.1 定義遊標
declare mycursor cursor for select*from yuangong
2.6.2 打開遊標
open mycursor
2.6.3 提取數據
Fetch next From Cur Into @ID,@DEVICEID ,@NAME ,@WORKGROUP ,@USERDOMAIN ,@OSNAME ,@OSVERSION ,@OSCOMMENTS ,@PROCESSORT ,@PROCESSORS ,@PROCESSORN ,@MEMORY ,@SWAP ,@IPADDR ,@DNS ,@DEFAULTGATEWAY ,@ETIME ,@LASTDATE ,@LASTCOME ,@QUALITY ,@FIDELITY ,@USERID ,@TYPE ,@DESCRIPTION ,@WINCOMPANY ,@WINOWNER ,@WINPRODID ,@WINPRODKEY ,@USERAGENT ,@CHECKSUM ,@SSTATE ,@IPSRC ,@UUID
執行提取數據以後的操作
While @@fetch_status=0 //如果有數據 Begin 。。。
最好加 再次提取數據 END
2.6.4 關閉遊標
Close Cur
2.6.5 釋放遊標
Deallocate Cur
2.7 OPENQUERY的使用
对给定的链接服务器执行指定的传递查询。该服务器是 OLE DB 数据源。
2.7.1 建立连接在db中,在server object 中,添加一个连接,用ole db 可以连接到任何一个 db。这样 就可以直接对这个连接进行查询了。
比如:连接的名称是OCS,db是ocsweb。然后读取ocsweb的语句 可以这样写。
SELECT a.* FROM OPENQUERY (OCS ,'select * from modems ')
其中modems表是ocsweb的db中的表。这样可以实现在 db中操作另一个db中的数据。
2.8 关于并发 ,设置时间戳 timestamp
更新使用下面的代码:
System.Data.SqlClient.SqlConnection conn =new System.Data.SqlClient.SqlConnection(); conn.ConnectionString = "Data Source=ITTSGSW-PC;Initial Catalog=ittsgsw;User ID=sa;Password=itts"; conn.Open(); string strSql = "SELECT * FROM [USER] WHERE id=@id"; System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(strSql,conn); command.Parameters.AddWithValue("@id", 1); System.Data.SqlClient.SqlDataAdapter ad = new System.Data.SqlClient.SqlDataAdapter(); ad.SelectCommand = command; DataTable dataTable = new DataTable(); ad.Fill(dataTable); byte[] bytes = (System.Byte[])dataTable.Rows[0]["mytime"]; strSql = "UPDATE [USER] SET name=@name WHERE id=@id and mytime=@mytime"; command = new System.Data.SqlClient.SqlCommand(strSql, conn); command.Parameters.AddWithValue("@id", 1); command.Parameters.AddWithValue("@name", 777); command.Parameters.AddWithValue("@mytime", bytes); int m= command.ExecuteNonQuery(); conn.Close();
读取的timestamp 这个字段,是byte【】数组,用byte【】数组保存内容。然后可以作为查询条件。进行更新。
select * from [user] where mytime=0x0000000000001779
update [user] set name='888' where mytime=0x0000000000001779