Trigger

http://www.codeproject.com/Articles/25600/Triggers-SQL-Server
create trigger my_trigger
on my_table
after insert, update
as
begin
declare @dt datetime = getdate();
update a
set expire_date = CONVERT(DATE, @dt, 101),
    expire_time = CONVERT(TIME, @dt)
from my_table as a
join inserted as b 
on a.product_no = b.product_no; 
end

go

使用 Trigger 紀錄資料表的新增、修改、刪除的行為

 

常被要求當資料表內的紀錄有被新增修改或刪除的時候,需要同步紀錄每次資料表變動的前後資料,這時候我們可以利用 Trigger 便可做到符合這個功能的需求,而且可以適用到大部份的使用情境,又因為 Trigger 本身也可以捕捉到資料庫的 DML 的事件,如 : INSERT、UPDATE 、DELETE ,我們也能捕捉在該資料列被修改之後 (AFTER DML) 才來執行 Trigger ,所以剛好滿足我們要記錄的資料表變動的行為。

Microsoft SQL Server 的 Trigger 內會包含有兩個特殊的虛擬資料表 inserted 與 deleted ; 這兩個資料表分別會擷取引發 Trigger 的資料列修改之前、後資料內容,當然它們會儲存單筆或多筆資料列更新的資料,下表說明了每個 DML 的操作內的 inserted、deleted 會包含的資料列之內容。

資料庫 DMLinserteddeleted
INSERT插入的新資料內容 
UPDATE欲更新的新資料內容更新前的舊資料內容
DELETE 被刪除前的資料內容

當有新的資料列插入該資料表時,會觸發  INSERT 事件,會複製該新增資料列的內容到虛擬資料表 inserted ,但不會存在有虛擬資料表 deleted ;  若是某筆資料列被更新了,那麼會觸發 UPDATE 事件,並且會複製欲更新的新資料內容到虛擬資料表 inserted ,同時將舊資料列內容複製到虛擬資料表 deleted ;  刪除某筆資料列的話,將觸發 DELETE 事件,此時會將刪除前的資料列內容複製到虛擬資料表 deleted ,因為沒有資料新增或更新,所以,不會存在有虛擬資料表 inserted 。

在後面附上的面的 Trigger 內容中的 6~14 行,我便利用上述的原理來判斷觸發此 Trigger 的 DML 事件為何? 所以,我們需要對於資料庫的運作原理是有進一步了解,才有辦法靈活運用的。

上面的一堆資料庫的運作原理,主要是我想在同一個 Trigger 中同時使用多個 AFTER DML 事件,因為我不想維護同一類的 Trigger 內容,當然,也得看使用的情境,如果你的 AFTER INSERT 還包含其他的運算邏輯,那建議還是將內容分開兩份 Trigger 比較恰當。

再者,之前看過很多範例 (包含我以前自己寫的) ,若要紀錄所有的歷史紀錄大部分是新增跟原始資料表相同的欄位 (Schema) ,頂多在後面新增一個資料欄位來記錄該筆是,update、insert 或 delete,這樣雖然可行,但我想到萬一原始資料表的欄位有新增、修改或刪除,那麼這個歷史資料表也要同步更新,而我們又有可能忘了同步更新,而造成某些欄位的資料內容沒有被記錄到,我考量到這個問題,且想提高此 Trigger 的重複利用性,因此,我想將該資料列內的資料內容全部存成 XML 資料格式,將此 XML 資料放在一個 XML 資料型態的欄位即可,當然這有個缺點是,當要調閱某筆歷史資料時,你可能沒辦法很簡單的就查詢到該筆記錄的內容,可能需要再使用其他方法來解析出 XML 的內容才行,這部分在稍後我也會提供一個方法技巧來做查詢的。

要將資料列轉換成 XML 格式的資料其實不難,只要利用 SQL Server 2000 以後提供的  FOR XML ,便可輕易的將資料表資料轉換成需要的任何 XML 內容格式了 ,在下方的 Trigger 內容中的 17 與 20 行便有使用到此功能。

但為了對 XML 內容的查詢方便,我選擇了使用 FOR XML RAW, ELEMENTS, ROOT 來產出我要的格式。

下方是我實作的一個範例,首先要建立一個新的 LOG 資料表來存放紀錄 :

   1: CREATE TABLE [dbo].[LOG](
   2:     [id] [uniqueidentifier] NOT NULL,
   3:     [dbname] [varchar](25) NULL,
   4:     [recoder] [xml] NULL,
   5:     [istype] [tinyint] NULL,
   6:     [updatedate] [datetime] NULL,
   7:  CONSTRAINT [PK_LOG] PRIMARY KEY CLUSTERED([id] ASC)
   8:  WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
   9: ) ON [PRIMARY]
  10: GO
  11: ALTER TABLE [dbo].[LOG] ADD  CONSTRAINT [DF_LOG_id]  DEFAULT (newid()) FOR [id]
  12: GO
  13: ALTER TABLE [dbo].[LOG] ADD  CONSTRAINT [DF_LOG_updatedate]  DEFAULT (getdate()) FOR [updatedate]
  14: GO

 

再來我們使用在 NorthWind 資料庫的 Customers 資料表內建立一個新的 Trigger ,此 Trigger 會在 Customers 資料表有被修改後觸發 :

   1: CREATE TRIGGER [dbo].[trCustomers_UPDATE_INSERT_DELETE] ON [dbo].[Customers] AFTER UPDATE,INSERT,DELETE
   2: AS
   3: BEGIN    
   4:     DECLARE @record XML   
   5:     DECLARE @IsType TINYINT
   6:     SET @IsType=''
   7:     IF EXISTS(SELECT 1 FROM inserted) AND NOT EXISTS(SELECT 1 FROM deleted)
   8:         SET @IsType = 1    --Insert
   9:  
  10:     IF EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
  11:         SET @IsType = 2    --Update
  12:  
  13:     IF NOT EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
  14:         SET @IsType = 3    --Delete
  15:     
  16:     --只想記錄 UPDATE 事件更新資料前的舊資料
  17:     IF (@IsType = 1)    
  18:         SET @record=(SELECT * FROM inserted FOR XML RAW('Customers'), ELEMENTS,ROOT)
  19:     ELSE
  20:         SET @record=(SELECT * FROM deleted FOR XML RAW('Customers'), ELEMENTS,ROOT)
  21:  
  22:     IF (@IsType <>'')
  23:     BEGIN
  24:         INSERT INTO [log]([dbname],[recoder],[istype])VALUES('Customers',@record  ,@IsType) 
  25:     END
  26: END

 

上面的就已經做到我們要的儲存修改紀錄的功能了,不過美中不足的是這樣的資料結構不是那麼的方便查詢,必須要再利用 OPENXML 將 XML 資料取出來。

假設要追蹤某一筆記錄,你可以先使用 SQL 指令查詢到該筆記錄後,將 Log 資料表的 recoder 欄位的 XML 資料丟給 OPENXML 處理即可,如下方法 : (其實這方法可以應用在 Master and Detail view 情境中, 也就是你將之前的紀錄先以類似 GridView 的列表顯示所有紀錄後, 再使用 DetailsView 等將詳細的紀錄顯示出來)

   1: DECLARE @xmldoc XML
   2: SELECT @xmldoc = recoder FROM Log WHERE [id]='AF35C6FF-E36E-41D5-9158-911931ABDB19'
   3:  
   4: DECLARE @hDoc AS INT
   6: EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmldoc
   7: SELECT *
   8: FROM OPENXML(@hDoc, '/root/Customers', 2)
   9: WITH ([CustomerID] [nchar](5),
  10:     [CompanyName] [nvarchar](40),
  11:     [ContactName] [nvarchar](30),
  12:     [ContactTitle] [nvarchar](30),
  13:     [Address] [nvarchar](60),
  14:     [City] [nvarchar](15),
  15:     [Region] [nvarchar](15),
  16:     [PostalCode] [nvarchar](10),
  17:     [Country] [nvarchar](15),
  18:     [Phone] [nvarchar](24),
  19:     [Fax] [nvarchar](24)) 
  20:  
  21: EXEC sp_xml_removedocument @hDoc


【源码免费下载链接】:https://renmaiwang.cn/s/in99a PDFMerge 是一个实用工具,主要用于将多个独立的PDF文件整合到一个单一的PDF文档中,这对于管理和分享大量的PDF文档非常有帮助。这个工具基于JavaScript开发,因此它可以在Web环境中运行,无需安装任何桌面应用程序。在JavaScript开发领域,这样的工具属于“其它杂项”类别,可能涉及到前端开发、文件处理以及用户交互等多个方面。在JavaScript开发中,实现PDFMerge功能通常会涉及到以下几个关键知识点:1. **文件读取和处理**:JavaScript中的`FileReader` API用于读取用户上传的PDF文件。通过`readAsArrayBuffer`方法,可以将PDF文件转换为二进制数据,为后续的合并操作做准备。2. **PDF解析**:为了合并PDF,需要理解PDF文件的结构。虽然JavaScript中没有内置的PDF解析库,但有一些开源库如`pdfjs-dist`可以帮助解析PDF文档。这些库能解析PDF文件并提取必要的信息,如页面、元数据等。3. **PDF合并**:合并PDF文件的关键在于将各个PDF的页面添加到新的PDF文档中。这通常涉及到创建一个新的PDF文档对象,然后将旧PDF的页面对象复制到新文档中。使用开源库如`pdf-lib`或`PDF.js`可以实现这一过程。4. **文件操作与导出**:完成合并后,需要将新PDF以二进制形式写回,通常会用到`Blob`和`URL.createObjectURL`来生成一个可下载的URL。用户可以通过点击链接下载合并后的PDF。5. **用户界面设计**:为了方便用户使用,需要设计一个友好的用户界面。这包括文件选择控件、进度指示器、错误提示等。React、Vue或Angular等前端框架可以用来构建这样
【源码免费下载链接】:https://renmaiwang.cn/s/crqbb 微信小程序是一种轻量级的应用开发平台,主要用于在微信内提供便捷的服务和丰富的用户体验。这个"微信小程序-商城功能(书店).zip"压缩包显然包含了用于构建一个专门针对书店的微信小程序商城的源代码和资源文件。下面我们将深入探讨相关的知识点。1. **微信小程序基础**:微信小程序是由腾讯公司推出的一种不需要下载安装即可使用的应用,它实现了“触手可及”的梦想,用户扫一扫或搜索即可打开应用。开发者可以使用微信提供的开发工具和框架进行开发。2. **小程序架构**:微信小程序基于 JavaScript、WXML 和 WXSS 三者构建。JavaScript 负责业务逻辑,WXML(WeiXin Markup Language)负责结构描述,而 WXSS(WeiXin Style Sheet)则用于样式设计。3. **商城功能**:商城功能是微信小程序中常见的一种应用场景,包括商品展示、购物车、订单管理、支付、用户评价等模块。在这个书店小程序中,可能包含书籍分类、搜索、详情展示、购买流程等功能。4. **书籍管理**:书籍数据通常存储在后台数据库中,通过API接口与小程序交互。每个书籍条目应包含书名、作者、出版社、价格、库存等信息,以及书籍封面图片。5. **用户界面设计**:WXML 和 WXSS 的组合使得开发者可以创建出原生感强、响应式的界面。书店小程序可能会有轮播图、商品列、商品详情页、购物车页面等。6. **支付功能**:微信小程序内置了微信支付接口,开发者需要配置商户号、支付密钥等安全参数,用户可以通过小程序直接完成支付操作。7. **订单系统**:订单管理是商城功能的核心部分,包括下单、确认收货、退款/售后等流程。开发者需要设计数据库模型来存储订单信息,如订单号、商品信息、用户信息、状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值