Pages

顯示具有 程式語言 標籤的文章。 顯示所有文章
顯示具有 程式語言 標籤的文章。 顯示所有文章

2010年10月26日 星期二

無法解析 equal to 作業中 "Chinese_Taiwan_Stroke_CI_AS" 與 "Chinese_Taiwan_Stroke_BIN" 之間的定序衝突

如果在曾在不同版本的 SQL Server 上搬移過 Database,或是匯出、匯入過不同語系的 Database,都很有可能在下 SQL 語法的時候發生資料庫「定序」(Collation)錯誤的問題,那… 定序(Collation)到底是什麼咧?我相信妳看到這裡一點都不會想知道,所以我今天是說給其它一些想了解的人聽的。

「定序」到底是什麼?最簡單的來說,就是決定資料在資料庫裡排列的方式。聽起來好像也沒什麼大不了的,就只是排列的方式嘛… 對吧對吧?排列的方式可以有多重要?可以比吃飯重要嗎?只要結果資料可以秀出來,排列不對只是個小事而已,其實,我當初也是這樣想…

說到這裡,感覺好像還聽不出什麼重點。就讓我直說吧,當兩個 table 定序不同的時候如果有做 join 的動作,那就一定會發生「無法解析 equal to 作業中 xxx 與 ooo 之間的定序衝突」,因為 SQL Server 無法得知妳到底要遵從哪種定序,所以就直接給妳錯誤然後死在那裡,超級不負責任,跟我完全不一樣!

舉個例子,我們都知道 SQL 裡的 Order By 欄位,不過我們所謂的 Order By 欄位到底是 Order By 欄位裡的什麼呢?英文大小寫有差嗎?字體的全形半形有影響嗎?如果欄位裡面存的是中文資料,那是 Order By 筆劃嗎?還是發音?講了這麼多,「定序」(Collation)就是在做這件事。

如果在妳的 MS SQL Server Management Studio 上的 Database 上按滑鼠右鍵,妳可以在資料庫屬性裡的「一般」或是「擴充屬性」裡看到這個資料庫目前設定的「定序」是什麼。

妳目前所看到的是「Chinese_Taiwan_Stroke_BIN」,前面「Chinese_Taiwan」指的是語系,而後面 BIN 則是指「Binary」的意思,換句換說,就是表示目前是使用 Binary 來做排序,而也因為每個字的 binary 值不同,所以也可說是是這些資料欄位是有區分大小寫的。

再舉個例子「Chinese_Taiwan_Stroke_CI_AS」,「CI」是指 Case Insensitive(不區分大小寫),「AS」是指 Accent sensitivity(區分腔調),其他比較常見的還有「CS」Case sensitivity(區分大小寫)、「AI」Accent Insensitive(不區分腔調),「WS」Width sensitivity(區分全形半形)等等,其中還有比較特殊的「BOPOMOFO」可以讓妳不依照筆劃反而是依照中文 ㄅㄆㄇㄈ 發音來排序。

說了這麼多,相信妳應該有了個底,接下來就是整篇的重點了,萬一妳在 join 兩個定序不同的 table 而發生了譬如說「無法解析 equal to 作業中 "Chinese_Taiwan_Stroke_CI_AS" 與 "Chinese_Taiwan_Stroke_BIN" 之間的定序衝突」的問題,那該怎麼辦?這個可以區分為兩個主要解決辦法。

如果妳是開發人員角色,且在沒有辦法去修改後端資料庫時,最簡單的辦法就是在妳所 Join 的 table 後面直接加上 Collate 新定序名稱,這樣就解決了。例子如下
select EmpId, EmpName, CityName from Emp
join City on Emp_CityId=CityId collate Chinese_Taiwan_Stroke_CI_AS
where EmpId='9F40460'
簡單吧!我就說,我也不懂為什麼外面的書籍或是教學文件為什麼要弄得那麼複雜。好吧,接下來就有一些些複雜了,如果妳是資料庫管理人員,而妳在無法更動程式的狀況下,想要直接一勞永逸修正資料庫來解決問題,就要照以下的步驟來做。

如果妳想要更改整個資料庫的定序,妳必須下以下的指令,因為在 MS SQL Management Studio 裡是不允許妳直接修改定序(避免妳操作不當選擇了錯誤的語系而把整個資料庫毀了)。
ALTER DATABASE 妳的資料庫名稱 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE 妳的資料庫名稱 Collate Chinese_Taiwan_Stroke_CI_AS
ALTER DATABASE 妳的資料庫名稱 SET MULTI_USER WITH ROLLBACK IMMEDIATE
第一行是鎖定目前資料庫給妳一個人使用,避免其他人更新,最後一行是恢復成多人使用,而第二行則是設定妳所想要的定序名稱。這個指令,不僅會直接更改資料庫的定序,連同這個資料庫下面的所有 tables 也都會被更改成這個新的定序,不過… 這邊就要聽好,重點來了,這個也僅只會更改「資料庫」與「Table」的定序,而 Table 下的欄位也有自己的定序,通常預設是跟 Table 一樣,不過有時候也有例外的情形…

如果以上的指令下過了,妳還是發生同樣的定序錯誤,那妳就得看一下 SQL 語法到底是哪個欄位與欄位之間做 join 時定序發生錯誤,而直接去修改那個欄位的定序。

修改欄位的定序可以在 MS SQL Management Studio 上直接設定。

可以指定或或是使用目前 Table 的預設值(還原預設值)。

不過… 天底下有時候就是這麼剛好有這麼衰的事,當妳無從得知程式背後是如何運作的同時,又剛好發生定序錯誤… 唯一的辦法,就是一個 table、一個 table、一個欄位、一個欄位的掃一遍了… 而這種好死不死的衰事,最近這幾天就剛好發生在我身上… 唉…(要不然也不會有這麼枯燥的這篇出現了)

2010年6月28日 星期一

Web Service(1)五分鐘速成

話說,打從我開寫 Blog 以來,好像就少有正經不嘴砲的文章,除了少有幾篇關於 SQL 或是關於四捨五入的教學外,對整個社會貢獻一丁點也沒有,所以我決定要塞幾篇有些教學性質的文章,已避免這裡的素質太過低落。

今天我想要來談談 Web Service,雖然說 Web Service 不是什麼高深的新技術,但是有鑑於網路上對於 Web Service 的中文實用範例過於稀少,加上大部分都是英文居多,那我就來個中文的簡易版,五分鐘教妳學會怎麼使用 Web Service。

在開始解說之前,我一定要先保證,這絕對是一篇對某些人實用,對大部分的人會無聊會打瞌睡的文章…

什麼是 Web Service?根據 Google 上面所解釋
Web Service 是一種面向服務的架構的技術,通過標準的Web協議提供服務,目的是保證不同平台的應用服務可以互操作。
有聽沒有懂?嗯… 相信我,這是正常的。因為我通常對這些官方解釋都直接跳過,直接進入實例,等寫完實例後再回頭看解釋,保證妳同醍醐灌頂,覺得那些解釋根本寫得比我還八股!我給予它白話的解釋是
Web Service 是在網路上的服務,寫程式的時候妳可以使用它回傳給妳的值來完成妳的程式。
對,就這樣,我給它的解釋不會更多,輕鬆簡單白話易了。舉個例子,今天妳有個程式需要做幣值間匯率的轉換,當然,或許妳的程式不需要這麼的精準,給它個固定匯率就可以了,可是通常這種狗屎運不會這麼多,妳要的是每天的最新匯率,這下子好了,我到底要怎樣去每天更新我程式裡的幣值匯率啊?這時候妳就需要 Web Service 了。

試想一下,不管是白天還是晚上,不管是昨天還是今天還是明天,妳就是要最當下的匯率資訊,而當這個服務存在網路上而且隨時可提供給妳,妳所需要的,只是需要時連上網路去取得這個匯率(使用 Web Service),而妳完全不需要懂這個服務背後是怎麼運作的,這樣妳的工作是不是就少了一大半了?換句話說,諸如此類的還有萬一我想取得天氣預報、取得即時新聞、取得郵遞區號、通訊錄等等,妳所需要做的,就只是上線取得這個服務,或是建立服務給他人使用而已,而今天這篇,則正是要舉個如何取得當下幣值匯率轉換來做例子。

打開妳的瀏覽器,隨便搜尋一下 asmx,妳會發現有許多可以使用的服務。.asmx 是 Web Service 的副檔名,就像是 .exe、.html 一樣。現在,在妳的瀏覽器網址列內輸入

http://www.webservicex.net/CurrencyConvertor.asmx

如果 Web Service 有正常運作,妳應該會看到以上的畫面。從畫面上妳可以知道這個 Web Service 叫做 CurrencyConvertor,裡面有個 Function 叫做 ConversionRate,還有一些解釋,大意就是這個服務是用來得到幣值與幣值之間的匯率。在開始寫程式之前,我們可以先試試看這個 Web Service 會不會動,點進入畫面的連結 ConversionRate ,然後把畫面往下拖拉到中間直到看到這個畫面

幣值可以隨意妳輸入,不過只能輸入它 List 裡面所提供的,就是畫面上洋洋灑灑看似一堆的幣值縮寫。因為下個星期我又要去香港玩了,所以我們拿港幣還有台幣來試試看。然後在 FromCurrency 內輸入 HKD,在 ToCurrency 內輸入 TWD,然後按下 Invoke。

噹噹!我們很幸運的,也很快速的在畫面上得到了以下這個值(見鬼了,港幣又漲了嗎?)

現在我們確定這個 Web Service 是上線且有在運作的,接下來,我們就來試試如何把這個 Web Service 跟我們的程式做連結。我們現在開啟 Visual Studio 2005 然後建立一個 Web Application(妳也可以使用 Window Form,只是我們這邊使用 Web Application 做例子)。

專案/網站名字可以自己取妳想要的,我這邊取名為 TEST_WebService,接著下一個步驟,就是如何引用一個 Web Service。

在工具列上選擇「網站」->「加入 Web 參考」。




然後接著把 Web Service 的所在網址輸入,我們的例子也就是剛剛我們所測試的網址,輸入 http://www.webservicex.net/CurrencyConvertor.asmx 然後按下

如果一切無誤,妳應該會看到上面那個畫面,妳可以把 Web 參考名稱換成妳想要的名字,在這裡我更名為 WS_Currency,建議妳跟我取的一樣,這樣後面妳我的名字比較不會混淆。然後按下「加入參考」按鈕。加入後,妳會發現到在妳畫面右邊的方案總管理多出了 App_WebReferences - WS_Currency。



現在到這邊,我們已經完成百分之八十的工作了,簡單吧!妳還沒敲入任何一個 code 咧!現在我們要接著完成剩下的百分之二十。打開 Default.aspx.cs,敲入以下圖片中的 Code,用圖片的原因是防止妳複製貼上,親自打一遍比較容易寄得住呀!(好吧… 其實是咔圖比較容易啦)

如果引用正確,當妳敲入 WS_Currency. 的時候,Visual Studio 的 intellisense 應該會自動帶出幾個類別,我們在這裡要選 CurrencyConvertor,也就是這個 WebService 的名稱。

或許妳會接著問,這個類別裡有這麼多的函數,我怎麼知道要使用哪個呢?其實秘密就在剛剛妳在瀏覽器裡輸入的 Web Service 網址後所出現的畫面內容裡。回顧一下,當我們輸入完 http://www.webservicex.net/CurrencyConvertor.asmx 之後,點入 ConversionRate 連結,把畫面拉到最下面,注意一下裡面有一段 XML 格式的內容,這個就包涵了我們所需要的資料。



Tag:ConversionRate 是一個函式的名稱(在一開使進入 Web Service 網頁的內容裡妳也可以見到)裡面包涵了兩個參數,分別是 FromCurrency 和 ToCurrency(還記得我們之前在網頁上所輸入的 FromCurrency 和 ToCurrency 嗎?),而 FromCurrency 和 ToCurrency 後面又接著一堆幣別代碼,那就是可輸入參數的內容值。因為這個 Web Service 已經對幣別做了定義,所以我們不能直接輸入 "HKD" 或是 "TWD",而是要使用這個類別裡所給予的 Currency 型別。照下面打就對了,我們要做的,就是把原本在網頁上所輸入的,改寫到從程式裡輸入而已。



沒多餘的廢話,重要的東西到這邊就結束了,簡單吧!接下來所得到的結果就看妳要怎麼運用了!下面就是把所得匯率 4.1178 放到 label 裡,全部的 Code 如下… 到這邊,妳應該知道一個 Web Service 是如何使用的了。



就這樣短短的三四行就可以隨時得到最新的匯率,不需要什麼高深的功夫也不需要什麼深度的知識,很簡單的妳就知道怎麼使用一個 Web Service。這篇從頭看到尾需要多少時間?不多不少五分鐘剛剛好!

因為 Web Service,從前一些程式與程式之間的跨網路合作,也開始變得可能!也因為既然是跨網路,當然也表示它也是跨平台,只要連上網,就能使用 Web Service!這也代表著如果要隨時更新異地程式與程式間的訊息,如果有 Web Service 做媒介,從前很複雜的一件事現在也可以變得很簡單,好了… 我想妳應該也快睡著了,今天就講到這裡吧… 同學們!下課~

2009年12月4日 星期五

SQL 實用的小工具 Query Express

有些事情不用大家的提醒我也知道,就是最近我的懶散、拖稿情形已經破了我歷年來的紀錄,為了避免流失廣大的讀者群,我決定今後不管再怎麼忙,不管是程式小工具也好、生活起居雜事也好、還是八卦流言打屁,反正就是要隨便找件事來寫寫。而且篇幅盡量縮短,廢話少一點,然後篇數盡量多一點,這樣子我相信一定可以讓大家看了有點像歹戲拖棚的感覺(誤),哈哈哈~ 不錯吧?真是讓我不免開始佩服我自己起來。

好事就要從現在做起,我決定今天就來介紹一個程式開發人員不能錯過的好工具。話說,微軟釋出 SQL Server 新版的速度真的是越來越快,而也有許多人遇到手邊的系統沒有辦法全部即時更新的問題,常常系統 A 是用 SQL Server 2000,系統 B 是用 SQL Server 2005,然後新上的系統又是 SQL Server 2008,更別說來插花的 Oracle 和 MySQL 了。

接著,你就會開始遇到手邊舊版的 Microsoft SQL Server Management Studio 連不到新版的 SQL,接著裝了新版的 SQL Server Management Studio Express 卻又發現跟舊版的 SQL 失連了,先撇除這些安裝檔又大(.NET Framework、powershell),安裝步驟又麻煩,光是為了解決這些重重微軟所出的考題,搞到最後我想自己也不知道電腦到底裝了幾套 SSMS… 所以,這時候有個好東西就出現了 - Query Express !

Query Express 畫面

登登!軟體免費下載!小小的 100KB 就給了你大半的世界,支援 SQL Server (2000 到最新)、Oracle,加上是綠色軟體免安裝,小小一個放到隨身碟或是網路上就可以帶著走,雖然功能陽春,不過至少提供了 SQL 指令與 T-SQL,小小的 100KB 我還能奢求什麼咧?有了她我就可以直接對各版本的 SQL Server 連線下指令啦,連 Oracle 和 MySQL(使用Query ExPlus)都不是問題喔~ 另外,作者也寫了超讚的 LINQPad 給想寫 LINQ 的人,當然也是免費,我的媽,真的是佛心來的!

如果有興趣的話,就趕快去把她抓回家吧!擺著供奉也好啊~

相關連結:Query Express 官方下載與介紹頁
相關連結:LINQPad 官方下載與介紹頁

2007年12月31日 星期一

SQL 日期 Convert 函數

好吧... 我承認這篇或許很無聊,不過對於一些 SQL 苦手/新手 在對於一些日期轉換的上面上應該多少有些些小幫助。

--------------------------------------------------------------------
Transact-SQL Server日期函數 CONVERT 範例

在 Transact-SQL 的預設日期 DATETIME 格式是 yyyy-mm-dd hh:mm:ss.mmm

例如:

SELECT GETDATE()
=> 2007-12-31 10:30:20.517

而在程式中常常需要日期的處理,尤其是什麼只要日期不要時間啊,只要時間不要日期啊,或是日期的 Format 等等,為了省掉在程式上撰寫轉換函數,這裡有些些 Transact-SQL 常用到的日期時間格式轉換,方法如下:

SELECT CONVERT(VARCHAR(18) , getdate(), 100)
=> 12 31 2007 10:30AM

SELECT CONVERT(VARCHAR(10) , GETDATE(), 101 )
=> 12/31/2007

SELECT CONVERT(VARCHAR(10) , GETDATE(), 102 )
=> 2007.12.31

SELECT CONVERT(VARCHAR(10) , GETDATE(), 103 )
=> 31/12/2007

SELECT CONVERT(VARCHAR(10) , GETDATE(), 104 )
=> 31.12.2007

SELECT CONVERT(VARCHAR(10) , GETDATE(), 105 )
=> 31-12-2007

SELECT CONVERT(VARCHAR(10) , GETDATE(), 106 )
=> 31 12 2007

SELECT CONVERT(VARCHAR(11) , GETDATE(), 107 )
=> 12 31, 2007

SELECT CONVERT(VARCHAR(8) , GETDATE(), 108 )
=> 10:30:20

SELECT CONVERT(VARCHAR(25) , GETDATE(), 109)
=> 12 31 2007 10:30:20:517AM

SELECT CONVERT(VARCHAR(10) , GETDATE(), 110 )
=> 12-31-2007

SELECT CONVERT(VARCHAR(10) , GETDATE(), 111 )
=> 2007/12/31

SELECT CONVERT(VARCHAR(8) , GETDATE(), 112 )
=> 20071231

SELECT CONVERT(VARCHAR(23) , GETDATE(), 113 )
=> 31 12 2007 10:30:20:517

SELECT CONVERT(VARCHAR(12) , GETDATE(), 114 )
=> 10:30:20:517

SELECT CONVERT(VARCHAR, GETDATE(), 120 )
=> 2007-12-31 10:30:20

最後
SELECT REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR, GETDATE(), 120 ),'-',''),' ',''),':','')
=> 20071231103020

這些全部已在 Transact-SQL 上測試過了
--------------------------------------------------------------

好吧,我承認,以上真的很無聊,很無聊

2006年10月11日 星期三

四捨五入的兩三事:Round 與 Format

平常在 Coding 的時候我四捨五入一直以來都是用 Round() 這個函數,自己也沒太多注意是否正確,因為自打從有印象以來,Round() 這個歸類在 Math Class 底下的函數就是我認知的四捨五入的用法,直到今天,測試了一下才令我嚇出一身冷汗...。

如果妳也使用 VB、ASP、或 ASP.Net 妳可以測試一下。舉個例子,1.115 四捨五入到小數第二位我們都知道應該是 1.12,使用 Round(1.115,2) 也可以得到 1.12 這個數字,我們再來看看 1.125 四捨五入到小數第二位,結果很神奇的是,Round(1.125,2) 並不會得到我們所預期的 1.13,Round(1.125,2) 回傳竟然還是 1.12,這到底是怎麼回事呢?是 Bug 嗎?

在微軟的 Knowledge Base 裡的 PRB: Round Function different in VBA 6 and Excel Spreadsheet 也有提到這個問題,在 Excel 裡所使用 Round 這個函數是正常的 (=Round(1.125, 2)),可是在 VB Like 的 program 裡卻不會,天... 真是令我百思不得其解,老大,我真的是想不透你啊...。後來再繼續找,接著在另一篇 How To Implement Custom Rounding Procedures 提到了說 Rounding 有分兩種,Arithmetic Rounding 跟 Banker's Rounding... 唉,我怎知道有這麼複雜.. 原來,我一直以來都錯了...。

Arithmetic Rounding 就是我們平常所說的四捨五入,我就不多說了。Banker's Rounding 我不知道是不是真的如同字面上所說的是銀行在用的,它也是四捨五入沒錯,只不過他是奇入偶不入,所以只有當遇到奇數位的時候會四捨五入 (所以 1.115 會進位成 1.12) ,否則就是四捨六入 (所以 1.125 是捨去變成 1.12,如果是 1.126 則變成 1.13)。據說這還符合國際標準咧,稿得還真複雜。除了 Round() 這個函數外 CByte()、CInt()、CLng()、CCur() 也都是使用 Banker's Rounding。

那到底要如何四捨五入呢?目前所想到是應該用 Format() 這個函式 (return string type)。1.115 四捨五入至小數點第二位則寫成 Format(1.115,".00") 就可以回傳正確值了,值得注意的地方是他會自動幫你補零,也就是如果是 Format(1.101,".00") 它會回傳 "1.10" 而不是 1.1,如果你要它回傳 1.1 則應該寫成 Format(1.101,".##"),這樣就不會幫妳補零了。

又是一個沉悶的東西,不過至少說不定對某些人搞不好會有點幫助。

2006年9月22日 星期五

SQL TOP N 的差異

- SQL SELECT TOP N equivalent in ORACLE and MySQL -

今天同事問了一個關於 MS SQL 和 Oracle 之間使用 TOP N 差異的問題,其結果大致上規類於...

使用 MS SQL 時
SELECT TOP 10 product, descr, email
FROM products

使用 Oracle 時
SELECT product, descr, email
FROM products
WHERE ROWNUM <= 10

使用 MySQL
SELECT product, descr, email
FROM products
LIMIT 10

以上大致如此,當然,如果再加上 Order By 的時候就得還要再加以修改。
譬如說在 Oracle 就得另外改成
SELECT product, descr, email
FROM (select product, descr, email from products order by product )
WHERE ROWNUM <= 10

諸如此類...

解決在 IE 上空白的問題

在 Blogger 架設完 "Skyer 時間紀元" 之後,玉姐跟我說她用 IE 開起來後是空白的一片,我心裡大叫「不會吧... 冏rz」

雖然曾經也曾遇過這種鳥事,不過沒有一次是真正去解決的,總是認為這是別人寫網頁時沒有寫好所發生的錯誤,就隨手點了右上角的叉叉直接把它關掉,這下子可好了,這次哪裡不發生,竟然發生在我的 blog 上...

平常習慣是 Maxthon、Firefox 瀏覽器交替著用,剛好 Firefox 上沒有問題,而相容性比較好的 IE 卻出了問題。Blogger.com 被 Google 購買之後品質沒道理會下降,應該會提升才對啊...
「村長說他 IE 看你的 blog 卻沒有問題耶...」玉姐透過 MSN 繼續跟我說道。
天... 事情更加複雜,有些 IE 可以,有些 IE 卻有問題,我相信我的 IE 是最乾淨的了... 所以直接把外掛影響給屏除了,就直接以 Firefox 和 IE 的差異性來著手...

查了一下線上的文獻,幾分鐘過後發現 IE 和 Firefox 在 "解析網頁編碼的順序" 上有一些差異性。IE 是先解析完內容標籤後,再解析 header 標籤,Firefox 則和 IE 剛好相反。
Blogger.com 的預設編輯與系是萬國語 (utf-8),所以裡面會有一行

"meta equiv="Content-Type" content="text/html;harset=UTF-8"

的東西,而剛好我的 title 裡有了 "時間紀元" 這四個 utf-8 編碼的中文,所以...

Firefox 先使用 utf-8 解析了 header,然後繼續使用了 utf-8 編碼繼續下去,所以沒有問題,而 IE 如果預設中文 big-5 編碼的話,解析完內容後解析了 header 發現是使用 utf-8 編碼... 就有可能造成錯誤致使中斷... 所以觀看原始碼你可以看到東西,螢幕上卻空白一片。

目前解決方法就是
  1. title 別使用中文
  2. IE 預設使用 utf-8 解析網頁
  3. meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / 擺到最前面,至少要比 title 還前面
果然,修改之後,不管是 IE 和 Firefox 來瀏覽都不會有任何問題了。

(如果是 spaces 發生這種情形的話大概就死路一條了,因為連修改都不能修改... 唉)