May 2007 - Posts

KB-SQL 2000->2005, Table Owner Issue

資料庫要從SQL 2000搬到SQL 2005,我最慣用的手法是:

1) 將SQL 2000的DB Detach
2) MDF, LDF檔案Copy到SQL 2005主機
3) 在SQL 2005上Attach
4) 移除新Attach上去DB中的原User資料(不然建立User Mapping時會因為User已存在而失敗)
5) 建立新User並設好User Mapping就大功告成!

今天遇到一個比較棘手的狀況: SQL 2000資料庫中的Table Owner並不是dbo,而是特定的User(例如: blah),SQL 2005會自動為你建立名為blah的Schema,並將Table歸於該Schema下,上述的步驟4)會因為有Table掛在blah Schema下無法Drop blah這個User...

我試出兩種解決方法,第一種是先將所有的Table所屬Schema改為dbo,這樣就可以將Schema跟User移除,依上述步驟做完,再將Table Schema改回blah。改Table Owner可以用sp_changeobjectowner,以下的T-SQL可以產生批次修改所有Table Owner的Script:

   1:  select 'exec sp_changeobjectowner ''blah.'+name+''',''dbo''' 
   2:  from sysobjects where xtype='U'
   3:  and name<>'dtproperties'

 第二種方法只將新DB的User 'blah'移除,但保留Schema 'blah'(Schema 'blah'的Owner先改成'dbo',而SSMS問你要不要一併移除Schema時選No),這樣就可以順利完成步驟5)。但記得做完後,要將User 'blah'的Default Schema設成'blah',而Schema 'blah'的Owner也要改回'blah'。

KB-IE 7 OnChange Behavior Change
<html><body>
<script>
function check() {
    var fld=document.getElementById("fld1");
    if (fld.value!="123")
    {
        alert("Must be 123!");
        event.returnValue = false;        
        fld.focus(); //or fld.select();
    }
 
}
</script>
<input type="text" name="fld1" onchange="check();" />
<input type="text" name="fld2" />
</body></html>

今天接獲報案,以上這段HTML在IE6上執行時,如果在fld1輸入非123的字串,點fld2後會彈出"Must be 123!",之後焦點回到fld1上,使用者若不信邪再點一次fld2,還是會彈出警語,阻止使用者離開fld1欄位,直到輸入123為止。

但同樣的程式在IE7上卻有不一樣的結果,第一次彈出警語後,若使用者"不要更改fld1的內容",再點一次fld2,此時IE7判定fld1的內容沒有改變,不算是onchange,因此就不再觸發第二次警告,使用者也得以把焦點移開fld1。

看起來,IE7對onchange的詮釋與IE6不同,我贊同Leo Horie的說法,IE7認為onchage=onblurafterchange,也就是修改後的那一次onblur才算數,從某個角度來說也沒錯,使用者沒有輸入或修改東西的情況下,是否也該算onchange? 就看你比對的對象是"上次修改前的內容"或是"上次onblur時的內容"? (或許IE Team認為他們終於把IE6錯誤的行為給校正了)

我還沒能找到說明這個行為改變的官方解釋,但現在知道的一個解決方法,是用onblur取代onchange,雖然可能觸發一些無謂的檢查,但至少同樣的Code在IE6及IE7上都管用。

KB-Nullable Value Type: varName == null ?

.NET裡的變數型別分為Value Type(如int, bool)與Reference Type(如StringBuilder, SqlConnection),其中Value Type的資料內容直接放在堆疊(Stack)中,不像Reference Type需要Pointer指向真正的資料位置,因而Value Type的變數沒法指定為null。(延伸閱讀: 1 2)

.NET 2.0提供了Nullable Value Type,實際上是用一個泛型結構(Generic Structure)去包裝Value Type,詳細的說明請大家看官方文件,這裡就不雞婆了。我學習Nullable Type時,只看了Nullable Structure Members文件就匆匆用了起來(其實我應該先看看Using Nullable Type的),關於資料是否為null的判斷就乖乖地寫成: if (i.HasValue) { j=i.Value; }

昨天同事小娟跟我說她測試的結果,其實寫: if (i==null) { j=i; }就可以了(驚! 我當了好一陣子的笨蛋)

親手做了測試,i==null的寫法OK,j=i的寫法有個但書,就是j必須跟i一樣是Nullable Type,不然Compile時會出錯。不過,我們共同的疑問是,i==null與i.HasValue的寫法當真完全相同? 會不會在某些情境下有特殊限制?

我驗證這個問題的方法是寫了如下的Code,Build成EXE檔後,再用ILDASM反組譯。

static void TestNullable()
{
    int? i = null;
    if (i == null)
        Console.WriteLine("i == null");
    if (!i.HasValue)
        Console.WriteLine("i has value");
    int? x = i;
    int y = i.Value;
}

ILDASM反組譯的結果,可以看到i==null與i.HasValue最後會被編譯成完全相同的MSIL Code。

.method private hidebysig static void TestNullable() cil managed
{
// Code size 64 (0x40)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> i,
[1] valuetype [mscorlib]System.Nullable`1<int32> x,
[2] int32 y,
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: ldloca.s i
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0009: ldloca.s i
IL_000b: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0010: stloc.3
IL_0011: ldloc.3
IL_0012: brtrue.s IL_001f
IL_0014: ldstr "i == null"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: nop
IL_001f: ldloca.s i
IL_0021: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brtrue.s IL_0035
IL_002a: ldstr "i has value"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: nop
IL_0035: ldloc.0
IL_0036: stloc.1
IL_0037: ldloca.s i
IL_0039: call instance !0 valuetype [mscorlib]System.Nullable`1<int32>::get_Value()
IL_003e: stloc.2
IL_003f: ret
} // end of method Program::TestNullable

由以上的分析來看,在C#中可以直接引用i==null,應該算是C# Compiler(CSC.EXE)的佛心來著,而我們在撰寫相關程式碼時,就大大方方享受這項貼心服務吧!

Posted 29 May 2007 03:31 PM by Jeffrey | 3 comment(s)
Filed under: ,
KB-SQL 2000 Reporting Service on Domain Controller

SQL 2000 Reporting Service安裝於Windows 2000 Domain Controller上,machine.config processModel的身份原本使用SYSTEM,基於安全考量改用IWAM_APName後,不幸的事就發生了。(註: 在Domain Controller上,ASP.NET不能用大家所熟知的ASPNET/NETWORK SERVICE帳號執行,請參考這篇文件的備註)

首先,Reporting Service跑出以下的錯誤訊息:
報表伺服器發生內部錯誤。請查看錯誤記錄以取得更多詳細資料。 (rsInternalError)
這個使用者設定檔是臨時的設定檔。

經驗中,Reporting Service的Log裡有詳細的訊息,追到熟知的C:\Program Files\Microsoft SQL Server\MSSQL\Reporting Services\LogFiles,卻沒看到我期待的詳細錯誤訊息。查了一陣子,才在事件檢視器中看到ReportManager發出的錯誤事件:
在預設的目錄位置中找不到追蹤記錄。追蹤記錄將建立在下列位置 : C:\DOCUME~1\BLAH\IWAM_Y~1\LOCALS~1\Temp\LogFiles

這是因為IWAM帳號沒有權限將檔案寫入該目錄的緣故(要解決的話,請改一下該目錄的NTFS的安全設定),所以只好另覓他處安放。(我覺得這個Log目錄有問題的Exception Handling很棒!!)

查看Log,找到詳細的錯誤訊息:
aspnet_wp!webserver!e2c!05/24/2007-19:40:09:: e ERROR: Internal error: System.Runtime.InteropServices.COMException (0x80090024): 這個使用者設定檔是臨時的設定檔。
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
at RSManagedCrypto.RSCrypto.ExportPublicKey()

用Reporting Servcie+0x80090024到Goggle拜一下,得知先前在改用IWAM帳號時,雖然有依http://support.microsoft.com/kb/824308的說明,賦與"用戶端在驗證後模擬"的權限。但IWAM屬於Guests群組,它不被進行一些加密金鑰的相關操作,所以會傳回0x80090024的錯誤訊息。解決的方法是將IWAM_MachineName自Guests群組中移除。移除完得重新開機才會生效,但苦難還沒結束...

Reporting Service改傳回以下訊息:
報表伺服器無法解密用來存取報表伺服器資料庫中機密或已加密資料的 Symmetric 金鑰。您必須還原備份金鑰或刪除所有加密內容,然後重新啟動服務。
The report server cannot decrypt the symmetric key used to access sensitive or encrypted data in a report server database. You must either restore a backup key or delete all encrypted content and then restart the service. Check the documentation for more information.

查了一下,要命!! 換Service Account後,Reporint Service的加密Key就失效了,必須依http://support.microsoft.com/kb/842421 的說明先備份Key,換Account,再設定Key...  只是Account都換了,來得及嗎?  幸好,我們只需先將machine.config先改回SYSTEM,讓Reporting Service再跑起來,就可以完成補票的工作。

手忙腳亂大半天,問題終告解決,Reporting Service又回來了。

【茶包射手專欄】ASP整合Excel檔處理的異常延遲

最近處理的一個案例:

ASP+VB COM的程式,會由資料庫提取Excel、Word、PowerPoint檔案,加上處理後放在暫存區供使用者連結下載。在某一部Windows 2000主機上,發生下載Word、Excel需一分鐘才能完成,PowerPoint卻只要幾秒鐘的狀況,而在其他主機上,幾秒鐘才是合理的速度。

依我的經驗,使用ASP呼叫Office Application是件危險的事,因為Office是為了前景作業而設計,雖然可以在ASP中以CreateObject("Excel.Application")的ActiveX Control模式叫用,但在背景環境下卻容易發生不可預期的結果,我就幹過在記憶體中留下上百個Excel.exe Process的輝煌記錄(汗)。(遇到這類狀況,我喜歡借重Excel可包容CSV、HTML的特性,直接Response.Write內容,再修改Response.ContentType為application/vnd.ms-excel,命令IE呼叫Excel解析呈現內容,例如這個範例)

面對這個問題,有點懷疑會不會是掃毒軟體搞的鬼。要驗證很簡單,拿出茶包射手吃飯的傢伙---萬用瑞士刀: Process Monitor,在LCD的鏡面反光前擺幾個Pose,覺得自己愈來愈像馬蓋先,帥呀~~~ 自High夠了,開啟ProcMon,設定Path Filter鎖定寫入Excel檔的目錄,接著啟動IE進行下載,果然要等上一分鐘才看得到Excel內容。

由ProcMon所觀察的檔案存取記錄發現幾點:

1.DLLHOST寫入Blah.xls,這是寫入Excel檔的程序
2.EXCEL.EXE讀取及寫入Blah.xls,這應是呼叫Excel.Application處理檔案的結果。
3.未發現掃毒軟體讀取Blah.xls的證據。
4有個MSIEXEC.EXE在EXCEL.EXE啟動後跳出來執行。

MSIEXEC.EXE是微軟的安裝程式,怎麼會沒事跑出來逛大街? 我想起一件事,從Office 2000/XP起,每個使用者第一次使用Word/Excel時,需要歷經一段初始化的過桯,有Progress Bar顯示進度,甚至會要求讀取Office的安裝光碟;但每個人只需初始化一次,以後就可直接開啟Word/Excel。而MSIEXEC.EXE,極有可能就是初始化動作背後的程序之一。由於初始化發生在背景,可能缺少了必要的互動,因此始終不能順利完成,導致了每一次叫用Excel.Application都要經歷一次初始化失敗的過程,這似乎就解釋了開Word/Excel特別耗時的原因。

解決方法很簡單,搞清楚呼叫Excel.Application的COM+ Application執行身份,使用該帳號登入Windows本機,分別啟動一次Word及Excel,果然彈出了要初始化的訊息。完成後,ASP處理Word/Excel的過程就快得跟飛的一樣了。

Case Closed!

令人心驚的IT鬼打牆

SQL 2005中的Common Table Expression(CTE)(註1)是很酷的新功能,比Temporay Table輕便(不用Create Table),又比Derived Table(註2)更耐用(建好後可以反覆使用),更不用說它還支援遞迴式參考的花式用法。

想當初在Beta版時代我寫過文章介紹SQL 2005的新功能,裡面紮紮實實地用範例介紹了CTE,沒想到今天發生可怕的鬼打牆,花了半小時連最簡單的CTE都建不出來。

由於打算寫一個很複雜的CTE,於是我照著語法範例先把宣告CTE的部分寫出來,其餘的部分想稍後再做:

WITH myCTE AS
(
SELECT * FROM MyList WHERE colA='123'
)

你猜怎麼著? SQL回了我一句,Msg 102, Level 15, State 1, Line 4 接近 ')' 之處的語法不正確。(英文原文為 Incorrect syntax near '(')

不會吧,CTE的宣告與範例上完全相符,WITH cte_name AS ( select blah )的寫法連白痴都不會寫錯。仔細檢查SELECT中有沒有拼錯字、全型半型弄錯,單獨拉出來跑一切正常,加入CTE後就是會嚷嚷著刮號附近的語法有問題。

於是我執著在"語法不正確"這件事上,檢查又檢查,換了台SQL 2005也是一樣,Google了半天找不到類似的案例回報,很快的,半個小時過去了... 畢竟身為資深茶包射手還是有異於常人的敏銳度,經驗告訴我,這一定是傳說中的

鬼打牆~牆~牆~~~~~

鬼打牆時有個特色,當事人會被困在正常人可輕鬆通過的地區,死命繞圈,無法脫困。遇到這種狀況,自己是走不出來的,最好由別人帶! 所以我馬上停止自己嘗試,MSN Call了幾個高手朋友,告訴他們我遇到鬼打牆了,請他們幫我看一下簡單到不行的語法哪邊出了問題。MVP朋友Bruce輕輕鬆鬆地指出來,我只要加個SELECT * FROM myCTE問題就解決了。

我想起很久前聽過的一個鬼故事,以前辛亥隧道是有衛兵站哨的,有一個深夜,執勤的衛兵看到隧道裡有台計程車停在原地不走。上前查看,隔著車窗看到司機慌張地看著前方,汗如雨下,一邊擦汗,還不斷看著手表,但車子似乎打到空檔。經驗老道的衛兵脫下小帽,用國徽的那一面用力拍了計程車的行李箱,頓時車子就飛也似地衝了出去... 剛才檢查了一下,我的電腦機殼上是有個國徽的印子。XD

【結論】

說是鬼打牆,其實應是SQL的錯誤訊息給得太模糊(底下如果隨便加個SELECT GETDATE(),錯誤會變成"Msg 422 定義了一般資料表運算式,但是未使用。"就正確多了),自己仗著以前有研究過,也沒規規矩地先Copy完整案例來試,就依自己的想法寫將起來,怪不得人。但這種當局者迷的經驗相信大家都有,像我這樣當機立斷,馬上停損請別人幫忙看(問題多簡單也不要怕丟臉,哈),已有好幾次成功克服盲點的記錄,推薦給大家參考。

註1: 可參考http://www.microsoft.com/taiwan/msdn/library/2004/Sep-2004/sql_ovyukondev.htm 關於"常見的資料表運算式"(真是爛到家的中文翻譯,SQL 2005後來自己翻成"一般資料表運算式")的說明
註2: 就是SELECT * FROM (SELECT * FROM T WHER A='1') AS X的這種寫法

SQL 2005 T-SQL Enhancement: Common Table Expression

從SQL 2000時代,相信不少人就知道運用Derived Table的技巧,將一段特定條件的查詢結果當作一個資料表來處理,讓整個查詢語句變得簡潔,且不必付出操弄暫存資料表的額外成本。不過,Derived Table與暫存資料表間還是有些差別,暫存資料表在建立後,可以反覆查詢,而Derived Table卻不行。CTE的出現打破了這項限制,兼具了Derived Table簡便輕巧的特性,也具備了如暫存資料表般可重覆使用的優點。

不過,改善了Derived Table無法重覆使用的缺點並不是CTE最受人矚目的突破,可以支援遞迴式查詢才是其最犀利的強項。這項特性很適合運用在複雜的階層式架構中,例如: 組織圖、BOM表…等等。

我們用一個PC組裝的零件清單作例子,假設組裝廠是依如上表的零件組合成模組、再組裝成PC,則我們可以用CTE的遞迴查詢技巧直接在T-SQL中建出整個關聯架構(程式如下)。

** CTE範例 **
--如果CTE的WITH不在第一列, 前方要加上;
;WITH DIYParts_BOM(PartName, Parent, Level, SortCol) 
AS
(
    --Recursive CTE分為兩個部分, 第一部分為Anchor Member
    --指不會被遞迴呼叫到的部分
    SELECT PartName, Parent, 0, CONVERT(nvarchar(128),PartNo)
    FROM DIYParts WHERE Parent=N'ROOT'
 
    UNION ALL
 
    --UNION ALL後方的部分稱為Recursive Member, 會在遞迴過程中反覆執行, 
    --直到無任何查詢結果為止
    SELECT P.PartName, P.Parent, B.Level+1, 
    CONVERT(nvarchar(128), B.SortCol+'-'+CONVERT(nvarchar(128),P.PartNo))
    FROM DIYParts P, DIYParts_BOM B
    WHERE P.Parent=B.PartName
)
SELECT REPLICATE('       ',Level) + PartName, Level, SortCol
FROM DIYParts_BOM ORDER BY SortCol 

遞迴式CTE內部分為兩個部分,以UNION ALL為界,前方的稱之為Anchor Member,後方的則為Recursive Member,遞迴呼叫時只有Recursive Member會重覆執行,一直執行到查無資料為止。當然,既然是遞迴,就要留意無窮迴圈的問題,最好能在事前防範,否則有個MAXRECURION參數可以設定最多的遞迴層數,超出時就產生錯誤。

FrontPage / Sharepoint Designer RegEx Replacement

今天才發現的,原來FrontPage/Sharepoint Designer的搜尋/取代功能可以支援類似Regular Expression的模糊比對,對我來說如獲至寶,馬上想到可以應用的幾個地方:

* 從Word Copy and Paste傳過來的HTML Code中老是夾帶一大堆不必要的Tag,雖然我已經寫過一台潛盾機做簡化,但用這個模糊比對加取代功能可以補足一些臨時性的彈性需求。

* 要在HTML中將某些字型、大小、顏色統一置換掉的時候。

總之,已經體驗過Regular Expression "字字珠璣,勝卻千言萬語"的開發者,自然知道怎麼用這個功能玩出各種奇技淫巧。只是它的語法跟標準的Regular Expression有些出入,例如:

. 表示任何字元

* 表示零或多個(愈多愈好)

+ 表示一或多個(愈多愈好)

@ 表示零或多個(愈少愈好,相當於RegEx中的*?)

# 表示一或多個(愈少愈好,相當於RegEx中的+?)

^n 重覆n次,相當於RegEx {n}

:a 文數字 :b 空白 :c 英文字母 :d 數字 :h 十六進位 ... 等等

[A-Z] 表示一組字元,跟RegEx中用法相同

^開頭 $結尾 \跳脫字符 ( ) 群組 都跟RegEx同

完整的說明可以看官方文件: http://office.microsoft.com/en-us/frontpage/HP030923241033.aspx

只是,不免要小小抱怨一下,為何不直接援引Regular Expression的語法就好了? 要多學一套,累~~

Posted 22 May 2007 11:27 PM by Jeffrey | no comments
Filed under: ,
KB-怪異的Permission Denied Script Error

同事有個網站,是一個http的網頁中,用<FrameSet>包了兩個https的<Frame> Frame1 & Frame2,三個網頁都在同一個網站上。問題來了,網頁在絕大部分的人的機器上都正常,就獨獨一位老兄的IE6,在操作過程中會出現Permission Denied的Script Error。

經檢查,問題出在Frame1中用了一段parent.Frame2.location.href的寫法去更動Frame2的URL,我們都知道這種寫法在跨Domain時會發生Permission Denied Error,但二個網頁明明是用https連向同一台Web Server,不應有跨Domain的問題存在才是。

我直覺判定這與<FrameSet>所在的URL是http脫不了關係,請他改用https,錯誤就消失了。

朝著這個方向在IE的安全設定中搜索,找到這個選項:

當這個選項被設為Diable時,http FrameSet中的https Frame間就無法互通。而Navigate sub-frames across different domains這個選項是設計用來阻止部分XSS攻擊,設定Disable是比較安全的,但事實證明這項限制也會造成某些網頁無法正常運作

為了避免User在"安全"與"可用"間天人交戰,我建議同事將最外層的http也改為https,就可避開此一限制。

【茶包射手專欄】CSI任務現場直擊

最近在看Yam天空新聞(http://news.yam.com 以前叫蕃薯藤新聞)時,我的IE6/IE7在檢視每一頁都會彈出以下的錯誤訊息。(FireFox則OK)

Object Expected! (中文叫做"此處需要物件") 而圖中所說的Line 73是
<script type="text/javascript" language="JavaScript" src="http://y.yam.com/sbox/srchbox_f.js"></script>

聰明的朋友們,想起來了嗎? Object expected不正是KB-留意js檔編碼問題一文中凡夫俗子型天打雷劈型提過的錯誤訊息,加上問題列為<script src>列,我有充分的理由懷疑這是一個js Encoding Issue

怎麼證明呢? 很簡單,開啟Fiddler擷取傳輸內容:

看到了嗎? /sbox/srchbox_fs.js,由Fiddler解析的結果可看到其中疑似中文編碼錯誤的亂碼(塗上橘色的部分)。Bingo!! CSI小組收工回家!

【茶包射手專欄】奧妙的IIS中文檔名解析

同事今天問了一個有趣的問題,有一個網頁檔"作業.htm",網頁裡有個圖檔叫"松鼠.jpg"。放在IIS的目錄下,開啟IE,URL輸入 http://myServer/作業.htm會傳回HTTP 404 找不到,但如果輸入http://myServer/松鼠.jpg則能正確Show圖!

一開始的質疑是,為什麼htm跟jpg的中文檔名處理原則不一樣? 不過想了想,htm又不是asp/asp.net會由另外的ISAPI程序處理,對IIS來說,都是讀取檔案再BinaryWrite罷了,為什麼會有如此差別待遇?

開啟Fiddler追蹤的結果,二個Request分別是
GET /%E4%BD%9C%E6%A5%AD.htm HTTP/1.1
GET /%E6%9D%BE%E9%BC%A0%.jpg HTTP/1.1

IE很忠實地將作業松鼠兩個字解析成UTF-8後以每個字三個Byte的十六進位碼傳回(想了解中文字如何解成UTF-8,可以參考我的中文編碼解析工具)。接著我到IIS上開啟Process Monitor,則發現當存取http://myServer/作業.htm時,IIS試圖去找一個檔名有亂碼的HTM檔案(雿平.htm),莫非---中文編碼解析錯誤? UTF-8被當成BIG5解了?

於是我把htm vs jpg的問題焦點改移到中文檔名所用的字上,多方排序組合測試的結果是,不管htm或jpg,只要檔名中有""這個字,就會發生檔案找不到的問題。而我的推論是,這種%E4%BD%9C%E6%A5%AD的資料對IIS來說,跟不知道語系編碼的狀況下要去讀檔案一樣,得靠一些特徵去"猜"是哪種編碼,而"業"的%E6%A5%AD剛好被判定成是Big5吧!

用我的中文編碼解析工具去看"雿平"三個字(第二字看不到),它的Big5碼不偏不倚,剛好就是%E4%BD%9C%E6%A5%AD,Bingo!!

所以我們可以確認,這個問題發生的原因是IE送出的中文檔名UTF-8編碼被IIS誤解為Big5。但IE為什麼要雞婆地將中文變成UTF-8呢? IE在進階設定的地方有個"Always send URLs as UTF-8"(愛台灣版為"永遠將URL傳送成UTF-8"),不知那一版本的IE起,這個設定預設為true。只要把這個設定關閉,http://myServer/作業.htm會送出
GET /作業.htm HTTP/1.1
反而不會出現誤解中文編號的問題,但這種方式不是所有Web Server都可以接受。

不過,面對中文檔名所帶來的諸多困擾,我建議的根本解決之道是:

1.避免使用中文檔名! 這是治本的方法,反正使用者都是靠Link連過來,用中文檔名對可讀性沒啥幫助
2.URL中如要加入中文,請使用JavaScript escape函數或ASP/ASP.NET Server.UrlEncode加入編碼

KB-SSIS Moving SQL NVarchar to ORACLE NVarchar2

之前用SSIS在做ORACLE與SQL間資料搬移時,最痛恨遇到NVarchar跟Unicode Code問題了。

明明是NVarchar(SQL)搬到NVarchar2(ORACLE),兩邊都Support Unicode,但SSIS都老會要求指定Data Flow Destination的Code Page,接著又會嚷著SQL中得到的Unicode不能直接轉成Non-Unicode,所以就得很可笑地在Nvarchar與NVarchar2兩個Unicode欄位中加上一個Data Conversion。如下圖:

不過,苦難還沒有結束... 如果很不幸地,NVarchar中還真的放了Unicode字元,則在轉換時,會出現以下的錯誤訊息。

Error: 0xC02020C5 at Data Flow Task Failure Sample, Data Conversion [543]: Data conversion failed while converting column "UnicodeField" (505) to column "UnicodeFieldMapping" (557). The conversion returned status value 4 and status text "Text was truncated or one or more characters had no match in the target code page.".
Error: 0xC020902A at Data Flow Task Failure Sample, Data Conversion [543]: The "output column "UnicodeFieldMapping" (557)" failed because truncation occurred, and the truncation row disposition on "output column "UnicodeFieldMapping" (557)" specifies failure on truncation. A truncation error occurred on the specified object of the specified component.

這問題讓我很困擾,不過因為遇到時都是做些一次性的資料搬移,所以我都很鄉愿地繞路解決(最愛用的一招是回去改用SQL 2000 DTS,很奇怪,用DTS搬資料時,幾乎不曾為Enocding傷過腦筋),未曾認真與它對決過。

最近同事想用SSIS來做重要的日常資料搬移,就卡在這個問題上,由於搬移是每天要跑的,繞路的成本就會高出許多,這回我總算被迫要收服這隻妖怪。東試西試之餘,忽然想到之前使用Query Express的經驗,Oracle的OLE DB Driver才能正確顯示Unicode,Microsft的OLE DB for Oracle反而不行,所以我試著把Data Flow Destination的OLE DB換成Oracle版。

美妙的事出現了!!  使用Oracle Provider for OLE DB後,連Data Conversion都不用了,直接對Unicode對Unicode,一次搞定。

看一下令人興奮的結果,SQL裡的六頭牛被搬到ORACLE裡了,NVarchar --> NVarchar2,萬牛奔騰的感覺豈是一個爽字可以形容,哈!!

Keyword: SSIS, SQL Server Integration Service, Oracle, NVarchar2, Unicode

手機中毒疑雲

昨天中午我的Sony Ericsson T610收到一封蜘蛛人3的簡訊廣告,通常我看到廣告簡訊後的第一個反射動作就是衝到簡訊收件匣殺殺殺,管你是電影首映封館出清低利貸款學生妹還是威而剛。但是... 這回簡訊收件匣空空如也~~~ 剛才那封廣告簡訊消失了。好樣的,不可能任務中看完會自爆的任務簡報影帶在我的手機裡真實上演。

之後,發現手機左上角通知有簡訊的那個信封圖示一直亮著(即使簡訊收件匣是空的),而更怪異的是信封符號上還有個被圓圈包起來的小寫w(像@,但中間包的是w),我第一個直覺是剛才的簡訊把手機搞到當機了,那個怪符號是中文big5解析錯亂所致。

今天換了電池,手機重開機後,該死的信封圖示加圓圈w居然還在! 這下不妙了,該不會是什麼簡訊病毒吧? 不過我懷疑是有收件匣看不到的簡訊存在,所以還去Download了最近版的floAt's Mobile Agent用藍牙連上T610查一下,從FMA看簡訊收件匣也是空的。

(雖然FMA沒能幫忙找出問題了,但FMA2.1版Beta4跟我兩年前試過的版本真不可同日而語,畫面變漂亮了、中文顯示也正常了。更酷的是,它還附上了手機遙控PC的功能,可以用藍牙手機放投影片,播MP3。以前付費軟體才做得到的功能,都一一在這套Open Source的軟體上實現了,在此向偉大的開發社群致敬!)

找不出原因,乖乖回來拜大神,用"T610 簡訊 符號"當關鍵字,總算查到一篇討論"消不去的郵件符號",症狀跟我相同,討論串中先是有人建議重設原廠設定,本來看到就有股衝動想照做,幸好耐著性子向下讀,有人提到WAP PUSH!! Yes, 莫非這就是圈圈w的由來。檢視了一下,果然在WAP PUSH的簡訊收件匣中,找到這封蜘蛛人3的廣告簡訊,殺!! Case Closed!

後記: WAP PUSH是一種內含超連結的簡訊內容,有支援WAP的手機可以按簡訊中的URL連至網站。

關鍵字: 手機 廣告 簡訊 怪符號

蠻橫小郡主的第一次母親節慶祝活動

算了算,蠻橫小郡主唸幼稚園也快一年了,雖然平日任性撒野絲毫不減,但倒也開始從老師、同學身上學到些東西。

女兒上學後的第一次母親節,先不管這小妮子是否真能誠心領悟到感恩這回事,學校倒是準備了很應景的活動,請了爸爸媽媽爺爺奶奶到學校,看小朋友表演,並有一個小小的點心餐會,頗有過母親節的氣氛。

中班小朋友一起表演了一個團體唱唱跳跳,挑的曲目當然來自幼兒界的發燒白金天碟---YoYo點點名(說老實話,"彩虹的約定"挺好聽的),雖然每位小朋友的動作都充滿了"自己的"特色,但只要看著小手小腳揮著擺著,再亂也叫可愛。

接著有分組表演,女兒居然有模有樣的敲起鐵琴,小女孩長大了(喜極而泣)~~

牆壁上有小朋友們的畫作--"我的爸爸/媽媽",據說有一張的模特兒是我,猜猜看吧!

最後來看我女兒的黏土創作,題目一樣是"我的爸爸媽媽"(旁邊是她手工製作的康乃馨哦),右方是她的媽咪,至於左方的把鼻看來有點怪,是因為要做嘴巴時,紅色黏土用完了,只好委曲地咬一顆橘子充數... 嗚嗚嗚(悲從中來)~~~

Posted 13 May 2007 02:19 AM by Jeffrey | 2 comment(s)
Filed under:
水龍頭漏水維修教學

陽台的水龍頭是八年前搬家時裝的,平時只用來澆花灑水。前陣子水龍頭開始有關不緊的現象,日益惡化的結果,這幾天已經到了旋到最緊時仍然保持每秒一滴的速度。雖然理性的算一下,這個速度一天下來也差不多是一次沖馬桶的量,但對天性摳門的我來說,點點滴滴,跟被人一直用小石子K頭沒什麼兩樣。更重要的是,最近全球暖化的議題喊得震天價響、天然資源將耗盡的問題正酣,若坐視我們家的水龍頭一直漏水下去,將有可能導致全球水資源耗盡、人類滅絕。於是,我決定即刻展開拯救全人類的偉大行動---把漏水的水龍頭修好。

算了算,叫水電行來修,少不了要好幾百塊,印象裡國中還是國小有學過水龍頭原理(腦海中浮現一個半剖的水龍頭構造,好像是在科展中看到的),這種陽春水龍頭似乎是用橡膠墊止水的,漏水應該換個墊圈就OK。Goggle了一下,證實了這點。二話不說,騎車到家裡附近的水電材料行,買了橡膠墊圈,雖然只要一個,但包裝是5個一組25元(這麼說還可以漏水再漏四次嗎?)。25/5... 本次材料成本---5元(忽略機車油錢及折舊)

所需工具:

1.螺絲起子: 裝卸上方的旋轉把手的固定螺絲
2.活動板手: 裝卸中央的止水結構

操作步驟:

1.先關閉水源開關(除非你想順便洗澡)
2.取下上方的固定螺絲,將旋轉把手拿下來
3.中央有個六角螺帽狀,用活動板手將它轉下來(要點蠻力)
4.拿出中央止水結構,下方應有一個黑色橡膠帽型止水墊(既然會漏水,此帽多已不成人形,呃... 不成帽形)
5.換上價值5元的全新止水墊
6.裝回止水結構、旋轉把手、上緊螺絲
7.打開水源總開關後,水龍頭應又是一尾活龍了

就這樣,只花了5元,耗時20分鐘,就改變了全人類的命運,實在功德無量,善哉善哉。 (自High中~~)

Posted 12 May 2007 02:39 AM by Jeffrey | 4 comment(s)
Filed under:
More Posts Next page »

Search

Go

<May 2007>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
 
RSS
【工商服務】


BlogLook Score and Rank

Syndication