關於branches,trunk,tags

簡單說明如下:

trunk: 放置當前程式開發進度,可能是非穩定版本;
tags: 放置穩定版本的資料;
branches: 準備發佈的版本,但有 bug 待修,修訂完畢後可以 merge 到先前版本。

吃最久的婚宴

https://www.ptt.cc/bbs/Anti-ramp/M.1285801086.A.4BD.html

看完心有戚戚焉,分享個十多年前的往事!!

那年剛出社會,參加了某黃同學的婚宴,辦在市政府附近有名的鬧鬼5星級酒店,
想說別失禮,特別準備了3000元的大紅包…
這對只領26K的我來說已是筆大支出了.

沒想到,沒想到…

這婚宴吃了4個小時吃不飽…一點都不誇張
雖知心靈課程是其家業,沒料居會如此置入行銷,
(心想,果然是未來的教主)
大多數的時間都由各分駝心得分享、呼口號,
再加上串場活動,極像造勢大會….

天呀!! 我只是來吃個飯的,快上菜吧!!
是刻意安排? 上菜極慢,等等等….等到吃不飽
(之後一群人自行續攤)

菜色嘛!! 就別提了,是吃裝潢的.

往後再有同學的婚宴,我總會提到此事…
應該…應該會被我一直…一直地唸到老…

減重之官方說法

說到我為什麼要減肥….除為了健康(無誤),
在這裡分享同事A的故事,必會心有戚戚焉.

沒錯,就是強者我同事,不要再問是不是我了.

某次廠商的女性業務來公司拜訪,和同事B Social了起來,
結了婚的男人最會的就是出一張嘴(嗯…別對號入座),
於是就開始了,妳單身喔!! 要不要幫你介紹之類的對話,
剛好聽到以下對話.

業務回:「若有好男生要幫我介紹呀!!」
同事B說:「可惜部門只剩同事A單身了」
業務回:「他喔!! 那可能要先去減個肥才有機會.」
我心裡的OS,天呀!!她還真敢講,
同事A的座位就在一旁,想必是明明白白+完完全全的聽到,
沒看到他的表情,但若是我就算開玩笑也鐵定大受打擊.

感同深受!!

那位同事A目前流亡海外,不知是否和此事有關….XD

游泳二三事

本人生性怕水,雖在二年前學過游泳,但沒多久就偷懶了.
可是近二個月卻克服心魔的瘋狂泡在水裡,原因有三:

一是已答應參加8月底的泳渡日月潭,錢都繳了,只能硬著頭皮練習(愛面子一族)
二是希望未來可以帶著自己的小朋友去泳池玩水(想像中~)
三是有同伴真的比較有動力(感謝蘇亮亮)

PS1.踢蛙腳的意外的好處是讓我屁屁變小了,而且也知道我的小腿是兇器….哈哈!!

PS2.一開始是怕沉下去,但現在想沉下去還不容易

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

原文: http://www.dotblogs.com.tw/jameswu/archive/2009/07/23/9643.aspx


備份如下:

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

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

資料庫 DML inserted deleted
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 資料表來存放紀錄 :

CREATE TABLE [dbo].[LOG](
     [id] [uniqueidentifier] NOT NULL,
     [dbname] [varchar](25) NULL,
     [recoder] [xml] NULL,
     [istype] [tinyint] NULL,
     [updatedate] [datetime] NULL,
  CONSTRAINT [PK_LOG] PRIMARY KEY CLUSTERED([id] ASC)
  WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
 ) ON [PRIMARY]
 GO
 ALTER TABLE [dbo].[LOG] ADD  CONSTRAINT [DF_LOG_id]  DEFAULT (newid()) FOR [id]
 GO
 ALTER TABLE [dbo].[LOG] ADD  CONSTRAINT [DF_LOG_updatedate]  DEFAULT (getdate()) FOR [updatedate]
 GO

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

CREATE TRIGGER [dbo].[trCustomers_UPDATE_INSERT_DELETE] ON [dbo].[Customers] AFTER UPDATE,INSERT,DELETE
AS
BEGIN
   DECLARE @record XML
   DECLARE @IsType TINYINT
   SET @IsType=''
   IF EXISTS(SELECT 1 FROM inserted) AND NOT EXISTS(SELECT 1 FROM deleted)
       SET @IsType = 1    --Insert

   IF EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
       SET @IsType = 2    --Update

   IF NOT EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
       SET @IsType = 3    --Delete

   --只想記錄 UPDATE 事件更新資料前的舊資料
   IF (@IsType = 1)
       SET @record=(SELECT * FROM inserted FOR XML RAW('Customers'), ELEMENTS,ROOT)
   ELSE
       SET @record=(SELECT * FROM deleted FOR XML RAW('Customers'), ELEMENTS,ROOT)

   IF (@IsType <>'')
   BEGIN
       INSERT INTO [log]([dbname],[recoder],[istype])VALUES('Customers',@record  ,@IsType)
   END
END

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

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

DECLARE @xmldoc XML
SELECT @xmldoc = recoder FROM Log WHERE [id]='AF35C6FF-E36E-41D5-9158-911931ABDB19'

DECLARE @hDoc AS INT
EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmldoc
SELECT *
FROM OPENXML(@hDoc, '/root/Customers', 2)
WITH ([CustomerID] [nchar](5),
    [CompanyName] [nvarchar](40),
    [ContactName] [nvarchar](30),
    [ContactTitle] [nvarchar](30),
    [Address] [nvarchar](60),
    [City] [nvarchar](15),
    [Region] [nvarchar](15),
    [PostalCode] [nvarchar](10),
    [Country] [nvarchar](15),
    [Phone] [nvarchar](24),
    [Fax] [nvarchar](24))

EXEC sp_xml_removedocument @hDoc

單眼皮女孩 之四:利用

話說這篇文章隔了三年,還真有夠久的…
只為了給這故事一個ENDING,本文再啟!!

不知從何時開始,FB上再也看不到她了,
是被封鎖了嗎? 還是被砍帳號?
一股腦的亂猜….也隨著時光流逝,
慢慢習慣沒有她的世界…..

「是因為我的問題嗎?」 我一直有著疑惑…

這事我父母、介紹人沒有再提及過,只是…….
後續還有發展…只是消息被隱藏了起來

據說因我的出現,前男友(?)有了危機感…
沒多久就下聘了…

故事結束!!

到頭我只是個被利用的角色!! 可笑~可笑~