2007年10月31日 星期三

寫入Event Log

將錯誤訊息或資訊寫入系統的log檔裡。
const string EVENT_LOG_NAME="Application";

EventLog log=null;
string message=null;

message="paladin test";
log=new EventLog();
log.Source=EVENT_LOG_NAME;
log.WriteEntry(message,EventLogEntryType.Information);
 
這樣,在事件檢視器裡的應用程式中,就會看到 message 裡的文字了。
EventLogEntryType是事件類別的列舉型態。有 Error, FailureAudit,
Information, SuccessAudit, Warning 可選擇。

將資料表B更新到資料表A

/*
資料表:

test1 (
TId int,
TA char(8)
)

test2(
BId int,
TA char(8)
)

程式需求:
將 test2 資料表的資料,當 TId=BId 時,將 test2.TA 更新到 test1.TA

程式說明:
透過 self-join 的原理,來完成

select tMake1.*
from test1 tMake1
inner join test1 tMake2
on tMake1.TId=tMake2.TId

接著修改成 update 語法 即可

*/

update tMake1 set
tMake1.TA = (select TA from test2 where BId=tMake2.TId)
from test1 tMake1
inner join test1 tMake2
on tMake1.TId=tMake2.TId

SQL-UNION

出現這個問題,剛好是因為我的資料表格裡面(MELearn)原先用來紀錄是否上架(IsShelf)與是否Demo(IsDemo)的欄位格式都是使用 int 格式. 但是在網頁呈現上,我應該用 是/否 來取代 1/0,所以就會有了下面這種轉換查詢結果的需求.

在這過程中,我發現畫線處的SELECT用法,是我所好奇的.原來
執行: SELECT #1 #2
會產生一個新的資料表格,裡面的值為 #1,對應欄位為 #2
執行: SELECT #1 #2, #3 #4
會產生

#2 #4
#1 #3

搭配 UNION的語法,就可以讓我們多加一筆新紀錄
所以下面的語法就會變成

ID NAME
1
0

SELECT MELearn.ELearnID,MELearn.LessonName,TMP1.NAME IsShelf,TMP2.NAME IsDemo
FROM MELearn
INNER JOIN (SELECT 1 ID, '是' NAME UNION SELECT 0 ID, '否' NAME) AS TMP1 ON MELearn.IsShelf=TMP1.ID
INNER JOIN (SELECT 1 ID, '是' NAME UNION SELECT 0 ID, '否' NAME) AS TMP2 ON MELearn.IsDemo=TMP2.ID

.Net 使用NTEXT

在.Net中,如果所要輸入的SQL參數格式是NTEXT時,要使用下面的格式,否則當內容字串超過一定大小後,會造成SQL指令執行錯誤。

sqlCmd.Parameters.Add("@Content",SqlDbType.NText);
sqlCmd.Parameters["@Content"].Value=Content;

SQL 執行逾期的問題

當執行比較費時的SQL語法時,雖然我們在 Query Analyzer裡執行不會出錯,但寫到程式裡頭時,卻會發生

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

的錯誤訊息。這是因為在 .Net 裡的 ADO 預設會對 SqlCommand.CommandTimeout 屬性設定 30,也就是只等待30秒,
如果clinet 端等待Server回應超過30秒以後,就會終止 。

所以,我們可以透過這個屬性,來設定我們期待可完成的時間。如果 CommandTimeout 設為 0,則表示無止盡的等待。
我們最好是盡量避免去做這種傻事,凡是要想開一些 ^_^

SQL Begin Transaction

在SQL語法裡,為了保證我們所寫的一段SQL語法裡都是正確,常常會使用 begin transaction / commit 來完成。範例如下:

begin tran;

update TFather set FName='111' where FID=1;


delete TFather where FID=1; --(故意會出錯的一行指令)

update TFather set FName='222' where FID=2;


if (@@ERROR<>0)
rollback tran;
else
commit tran;


我們通常會希望如果上面三行SQL指令有錯,自動RollBack 所有資料。然而,實際情況並非如此。他只會RollBack中間那行指令。第一、第三行指令都會被執行且修改到資料庫裡。這問題的解法,是要執行一行指令於 begin tran 之前:

SET XACT_ABORT ON

完整程式如下:

SET XACT_ABORT ON


begin tran;

update TFather set FName='111' where FID=1;


delete TFather where FID=1;

update TFather set FName='222' where FID=2;


if (@@ERROR<>0)
rollback tran;
else
commit tran;

SQL Server 判斷某個Table是否存在

假如要判斷資料庫中某個資料表格是否存在,可透過查詢 dbo.sysobjects 的結果來得知。
以下範例,是在查詢資料庫中是否有 Contactor這個資料表,而且這資料表的屬性是屬於 UserTable

if exists(
select * from dbo.sysobjects where id=object_id(N'[Contactor]') and OBJECTPROPERTY(id,N'IsUserTable')=1
)
select 1;
else
select 0;

select * from dbo.sysobjects

SQL Server 讓float 四捨五入

ROUND

傳回已經進位到特定長度或有效位數的數值運算式。

語法

ROUND ( numeric_expression , length [ , function ] )

引數

numeric_expression

是一個精準的數字或約略的數字資料型別類別 (但 bit 資料型別除外) 的運算式。

長度

指定 numeric_expression 所取的精確度。length 必須為 tinyintsmallint,或 int。當 length 為正數時, numeric_expression 會進位到取至 length 所指定的小數位數。當 length 為負數時,numeric_expression 會進位到取至小數點左邊,就如同 length 所指定的。

Function

指定欲執行的作業型別。function 必須為 tinyintsmallint,或 int。當 function 省略或值為 0 (預設值) 時,numeric_expression 會被四捨五入。當指定非 0 的值時,numeric_expression 會被截去小數點。

傳回型別

傳回與numeric_expression 相同的型別。

備註

ROUND 一定會傳回數值。如果 length 為負數,而且大於小數點以前數字的位數,則 ROUND 會傳回 0。

範例 結果
ROUND(748.58, -4) 0


 

當 length 為負數時,ROUND 會傳回經四捨五入的 numeric_expression 而不論其資料型別為何。

範例 結果
ROUND(748.58, -1) 750.00
ROUND(748.58, -2) 700.00
ROUND(748.58, -3) 1000.00
範例
A. 使用 ROUND 與估計

這個範例顯示兩個運算式,舉例說明以 ROUND 函數所得的最後一個阿拉伯數字一定是估計值。

SELECT ROUND(123.9994, 3), ROUND(123.9995, 3)
GO

以下為結果集:

----------- -----------
123.9990 124.0000
B. 使用 ROUND 與取其近似值

此範例顯示四捨五入與近似值。

陳述式 結果
SELECT ROUND(123.4545, 2)
123.4500
SELECT ROUND(123.45, -2)
100.00


 

C. Use ROUND to truncate

這個範例使用兩個 SELECT 陳述式來說明四捨五入與無條件捨去的差別。第一個陳述式將結果四捨五入。而第二個陳述式則將結果無條件捨去。

陳述式 結果
SELECT ROUND(150.75, 0)
151.00
SELECT ROUND(150.75, 0, 1)
150.00


SQL 判斷是否結果為NULL

要在SQL語法中判斷一個記錄或變數是否為NULL,不能直接用 if (@somevalue=NULL)
而是要用 if(@somevalue is null)

SQL Server 的NTEXT

在SQL Server的資料格式中,有些是屬於 NCHAR, NVARCHAR, NTEXT...等等前面有加上"N"的資料格式.這代表裡面存放的是屬於UNICODE資料.選擇這個欄位的好處,是不管使用者在裡面放哪一國的語言,都可以正確顯示出來.例如:簡體,韓文,日文

.Net Bug

問題: Windows XP 安裝微軟最新修正檔後,造成.Net 程式執行時,會出現Server端錯誤訊息

解決方法:

1.先關掉IIS

2.編輯 C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\CONFIG\machine.confi

用搜尋方式,找出唯一的 userName="machine" 接著把他改成 userName="system"

3.重新啟動IIS

2007年10月11日 星期四

IIS Worker Process

當IIS在處理每一個網頁頁面的時候,他的處理流程如右圖所示。

每一個頁面,會先經過 http.sys進行第一次的驗證。他針對每一個URL的請求,進行長度檢查,判斷是否有超過 16KB。16KB換算成字元數,是260個字元,也就是說,當你URL裡頭,有一個路徑是超過260個字元,則就會發出 414 的錯誤訊息。

HTTP Error 414 - Request URI too long

實際上,經過個人親自在 winXP、IIS 5.1與ASP.Net 2.0上測試,當超過260個字元時,出現的錯誤為 400

HTTP / 1.1 400 - 錯誤的要求時發生錯誤

這現象,是因為我並非在 windows2003 搭配 IIS6 的環境上所造成的差異。而右圖所提到的 w3wp.exe,也是要在 window2003上,才會有這個執行檔。

另外,如果想要觀察你的 WEB 站台處理了哪些URL請求,可以到 WEB站台的 %windir%\system32\LogFiles\W3SVC1 目錄下,找到所有的URL請求資料。

Http.sys他只會針對 URL 與 header 進行檢查,至於 Content 的檢查,則是交由ASP.Net去負責。

ISAPI(Internet Server Application Programming Interface)
ISAPI可執行文件分為兩類:擴展(Extensions)與篩選器(Filters)。
擴展的用法,是指可以透過像 http://localhost/myisapi.dll 這種方式來呼叫IIS所提供的功能來使用。
篩選器,則是能夠用來修改傳入與傳出的資料流。所以可以用來實作出自行定義的日誌記錄檔、身份驗證、也可以用來修改資料流。

2007年10月1日 星期一

SQL 語法裡的換行

如果在 C# 裡,要處理換行的符號,都是用 testString.Replace("\r\n","<br>")
可是在 SQL 與法裡,就不行這樣了,要改成 replace( testString,char(13),'<br>')

所以,SQL語法裡的換行是: char(13)