Oracle PL/SQL編程詳解之二:
PL/SQL塊結構和組成元素(爲山九仞,豈一日之功)
本篇主要內容如下:
2.1 PL/SQL塊
PL/SQL程序由三個塊組成,即聲明部分、執行部分、異常處理部分。
PL/SQL塊的結構如下:
--聲明部分: 在此聲明PL/SQL用到的變量,類型及遊標,以及局部的存儲過程和函數
BEGIN
-- 執行部分: 過程及SQL 語句 , 即程序的主要部分
EXCEPTION
-- 執行異常部分: 錯誤處理
END;
其中:執行部分不能省略。
PL/SQL塊可以分爲三類:
1. 無名塊或匿名塊(anonymous):動態構造,只能執行一次,可調用其它程序,但不能被其它程序調用。
2. 命名塊(named):是帶有名稱的匿名塊,這個名稱就是標籤。
3. 子程序(subprogram):存儲在數據庫中的存儲過程、函數等。當在數據庫上建立好後可以在其它程序中調用它們。
4. 觸發器 (Trigger):當數據庫發生操作時,會觸發一些事件,從而自動執行相應的程序。
5. 程序包(package):存儲在數據庫中的一組子程序、變量定義。在包中的子程序可以被其它程序包或子程序調用。但如果聲明的是局部子程序,則只能在定義該局部子程序的塊中調用該局部子程序。
2.2 PL/SQL結構
l PL/SQL塊中可以包含子塊;
l 子塊可以位於 PL/SQL中的任何部分;
l 子塊也即PL/SQL中的一條命令;
2.3 標識符
PL/SQL程序設計中的標識符定義與SQL 的標識符定義的要求相同。要求和限制有:
l 標識符名不能超過30字符;
l 第一個字符必須爲字母;
l 不分大小寫;
l 不能用’-‘(減號);
l 不能是SQL保留字。
提示: 一般不要把變量名聲明與表中字段名完全一樣,如果這樣可能得到不正確的結果.
例如:下面的例子將會刪除所有的紀錄,而不是’EricHu’的記錄;
ename varchar2(20) :='EricHu';
BEGIN
DELETE FROM scott.emp WHERE ename=ename;
END;
變量命名在PL/SQL中有特別的講究,建議在系統的設計階段就要求所有編程人員共同遵守一定的要求,使得整個系統的文檔在規範上達到要求。下面是建議的命名方法:
標識符 |
命名規則 |
例子 |
程序變量 |
V_name |
V_name |
程序常量 |
C_Name |
C_company_name |
遊標變量 |
Cursor_Name |
Cursor_Emp |
異常標識 |
E_name |
E_too_many |
表類型 |
Name_table_type |
Emp_record_type |
表 |
Name_table |
Emp |
記錄類型 |
Name_record |
Emp_record |
SQL*Plus 替代變量 |
P_name |
P_sal |
綁定變量 |
G_name |
G_year_sal |
2.4 PL/SQL 變量類型
在前面的介紹中,有系統的數據類型,也可以自定義數據類型。下表給出ORACLE類型和PL/SQL中的變量類型的合法使用列表:
2.4.1 變量類型
在ORACLE8i中可以使用的變量類型有:
類型 |
子類 |
說 明 |
範 圍 |
ORACLE限制 |
CHAR |
Character String Rowid Nchar |
定長字符串
民族語言字符集 |
0à32767 可選,確省=1 |
2000 |
VARCHAR2 |
Varchar, String NVARCHAR2 |
可變字符串 民族語言字符集 |
0à32767 4000 |
4000 |
BINARY_INTEGER |
|
帶符號整數,爲整數計算優化性能 |
|
|
NUMBER(p,s) |
Dec
Double precision Integer Int Numeric Real Small int |
小數, NUMBER 的子類型 高精度實數 整數, NUMBER 的子類型 整數, NUMBER 的子類型 與NUMBER等價 與NUMBER等價 整數, 比 integer 小 |
|
|
LONG |
|
變長字符串 |
0->2147483647 |
32,767字節 |
DATE |
|
日期型 |
公元前4712年1月1日至公元后4712年12月31日 |
|
BOOLEAN |
|
布爾型 |
TRUE, FALSE,NULL |
不使用 |
ROWID |
|
存放數據庫行號 |
|
|
UROWID |
|
通用行標識符,字符類型 |
|
|
|
|
|
|
|
例1. 插入一條記錄並顯示;
Row_id ROWID;
info VARCHAR2(40);
BEGIN
INSERT INTO scott.dept VALUES (90, '財務室', '海口')
RETURNING rowid, dname||':'||to_char(deptno)||':'||loc
INTO row_id, info;
DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id);
DBMS_OUTPUT.PUT_LINE(info);
END;
其中:
RETURNING子句用於檢索INSERT語句中所影響的數據行數,當INSERT語句使用VALUES 子句插入數據時,RETURNING 字句還可將列表達式、ROWID和REF值返回到輸出變量中。在使用RETURNING 子句是應注意以下幾點限制:
1.不能與DML語句和遠程對象一起使用;
2.不能檢索LONG 類型信息;
3.當通過視圖向基表中插入數據時,只能與單基表視圖一起使用。
例2. 修改一條記錄並顯示
Row_id ROWID;
info VARCHAR2(40);
BEGIN
UPDATE dept SET deptno=100 WHERE DNAME='財務室'
RETURNING rowid, dname||':'||to_char(deptno)||':'||loc
INTO row_id, info;
DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id);
DBMS_OUTPUT.PUT_LINE(info);
END;
其中:
RETURNING子句用於檢索被修改行的信息。當UPDATE語句修改單行數據時,RETURNING 子句可以檢索被修改行的ROWID和REF值,以及行中被修改列的列表達式,並可將他們存儲到PL/SQL變量或複合變量中;當UPDATE語句修改多行數據時,RETURNING 子句可以將被修改行的ROWID和REF值,以及列表達式值返回到複合變量數組中。在UPDATE中使用RETURNING 子句的限制與INSERT語句中對RETURNING子句的限制相同。
例3. 刪除一條記錄並顯示
Row_id ROWID;
info VARCHAR2(40);
BEGIN
DELETE dept WHERE DNAME='辦公室'
RETURNING rowid, dname||':'||to_char(deptno)||':'||loc
INTO row_id, info;
DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id);
DBMS_OUTPUT.PUT_LINE(info);
END;
其中:
RETURNING子句用於檢索被刪除行的信息:當DELETE語句刪除單行數據時,RETURNING 子句可以檢索被刪除行的ROWID和REF值,以及被刪除列的列表達式,並可將他們存儲到PL/SQL變量或複合變量中;當DELETE語句刪除多行數據時,RETURNING 子句可以將被刪除行的ROWID和REF值,以及列表達式值返回到複合變量數組中。在DELETE中使用RETURNING 子句的限制與INSERT語句中對RETURNING子句的限制相同。
2.4.2 複合類型
ORACLE 在 PL/SQL 中除了提供象前面介紹的各種類型外,還提供一種稱爲複合類型的類型---記錄和表.
2.4.2.1 記錄類型
記錄類型類似於C語言中的結構數據類型,它把邏輯相關的、分離的、基本數據類型的變量組成一個整體存儲起來,它必須包括至少一個標量型或RECORD 數據類型的成員,稱作PL/SQL RECORD 的域(FIELD),其作用是存放互不相同但邏輯相關的信息。在使用記錄數據類型變量時,需要先在聲明部分先定義記錄的組成、記錄的變量,然後在執行部分引用該記錄變量本身或其中的成員。
定義記錄類型語法如下:
v1 data_type1 [NOT NULL] [:= default_value ],
v2 data_type2 [NOT NULL] [:= default_value ],
......
vn data_typen [NOT NULL] [:= default_value ] );
例4 :
TYPE test_rec IS RECORD(
Name VARCHAR2(30) NOT NULL := '胡勇',
Info VARCHAR2(100));
rec_book test_rec;
BEGIN
rec_book.Name :='胡勇';
rec_book.Info :='談PL/SQL編程;';
DBMS_OUTPUT.PUT_LINE(rec_book.Name||' ' ||rec_book.Info);
END;
可以用 SELECT語句對記錄變量進行賦值,只要保證記錄字段與查詢結果列表中的字段相配即可。
例5 :
--定義與hr.employees表中的這幾個列相同的記錄數據類型
TYPE RECORD_TYPE_EMPLOYEES IS RECORD(
f_name hr.employees.first_name%TYPE,
h_date hr.employees.hire_date%TYPE,
j_id hr.employees.job_id%TYPE);
--聲明一個該記錄數據類型的記錄變量
v_emp_record RECORD_TYPE_EMPLOYEES;
BEGIN
SELECT first_name, hire_date, job_id INTO v_emp_record
FROM employees
WHERE employee_id = &emp_id;
DBMS_OUTPUT.PUT_LINE('僱員名稱:'||v_emp_record.f_name
||' 僱傭日期:'||v_emp_record.h_date
||' 崗位:'||v_emp_record.j_id);
END;
一個記錄類型的變量只能保存從數據庫中查詢出的一行記錄,若查詢出了多行記錄,就會出現錯誤。
2.4.2.2 數組類型
數據是具有相同數據類型的一組成員的集合。每個成員都有一個唯一的下標,它取決於成員在數組中的位置。在PL/SQL中,數組數據類型是VARRAY。
定義VARRY數據類型語法如下:
varray_name是VARRAY數據類型的名稱,size是下整數,表示可容納的成員的最大數量,每個成員的數據類型是element_type。默認成員可以取空值,否則需要使用NOT NULL加以限制。對於VARRAY數據類型來說,必須經過三個步驟,分別是:定義、聲明、初始化。
例6 :
--定義一個最多保存5個VARCHAR(25)數據類型成員的VARRAY數據類型
TYPE reg_varray_type IS VARRAY(5) OF VARCHAR(25);
--聲明一個該VARRAY數據類型的變量
v_reg_varray REG_VARRAY_TYPE;
BEGIN
--用構造函數語法賦予初值
v_reg_varray := reg_varray_type
('中國', '美國', '英國', '日本', '法國');
DBMS_OUTPUT.PUT_LINE('地區名稱:'||v_reg_varray(1)||'、'
||v_reg_varray(2)||'、'
||v_reg_varray(3)||'、'
||v_reg_varray(4));
DBMS_OUTPUT.PUT_LINE('賦予初值NULL的第5個成員的值:'||v_reg_varray(5));
--用構造函數語法賦予初值後就可以這樣對成員賦值
v_reg_varray(5) := '法國';
DBMS_OUTPUT.PUT_LINE('第5個成員的值:'||v_reg_varray(5));
END;
2.4.2.3 使用%TYPE
定義一個變量,其數據類型與已經定義的某個數據變量(尤其是表的某一列)的數據類型相一致,這時可以使用%TYPE。
使用%TYPE特性的優點在於:
l 所引用的數據庫列的數據類型可以不必知道;
l 所引用的數據庫列的數據類型可以實時改變,容易保持一致,也不用修改PL/SQL程序。
例7:
-- 用%TYPE 類型定義與表相配的字段
TYPE T_Record IS RECORD(
T_no emp.empno%TYPE,
T_name emp.ename%TYPE,
T_sal emp.sal%TYPE );
-- 聲明接收數據的變量
v_emp T_Record;
BEGIN
SELECT empno, ename, sal INTO v_emp FROM emp WHERE empno=7788;
DBMS_OUTPUT.PUT_LINE
(TO_CHAR(v_emp.t_no)||' '||v_emp.t_name||' ' || TO_CHAR(v_emp.t_sal));
END;
例8:
v_empno emp.empno%TYPE :=&no;
Type t_record is record (
v_name emp.ename%TYPE,
v_sal emp.sal%TYPE,
v_date emp.hiredate%TYPE);
Rec t_record;
BEGIN
SELECT ename, sal, hiredate INTO Rec FROM emp WHERE empno=v_empno;
DBMS_OUTPUT.PUT_LINE(Rec.v_name||'---'||Rec.v_sal||'--'||Rec.v_date);
END;
PL/SQL 提供%ROWTYPE操作符, 返回一個記錄類型, 其數據類型和數據庫表的數據結構相一致。
使用%ROWTYPE特性的優點在於:
l 所引用的數據庫中列的個數和數據類型可以不必知道;
l 所引用的數據庫中列的個數和數據類型可以實時改變,容易保持一致,也不用修改PL/SQL程序。
例9:
v_empno emp.empno%TYPE :=&no;
rec emp%ROWTYPE;
BEGIN
SELECT * INTO rec FROM emp WHERE empno=v_empno;
DBMS_OUTPUT.PUT_LINE('姓名:'||rec.ename||'工資:'||rec.sal||'工作時間:'||rec.hiredate);
END;
ORACLE提供了LOB (Large OBject)類型,用於存儲大的數據對象的類型。ORACLE目前主要支持BFILE, BLOB, CLOB 及 NCLOB 類型。
BFILE (Movie)
存放大的二進制數據對象,這些數據文件不放在數據庫裏,而是放在操作系統的某個目錄裏,數據庫的表裏只存放文件的目錄。
BLOB(Photo)
存儲大的二進制數據類型。變量存儲大的二進制對象的位置。大二進制對象的大小<=4GB。
CLOB(Book)
存儲大的字符數據類型。每個變量存儲大字符對象的位置,該位置指到大字符數據塊。大字符對象的大小<=4GB。
NCLOB
存儲大的NCHAR字符數據類型。每個變量存儲大字符對象的位置,該位置指到大字符數據塊。大字符對象的大小<=4GB。
2.4.5 BIND 變量
綁定變量是在主機環境中定義的變量。在PL/SQL 程序中可以使用綁定變量作爲他們將要使用的其它變量。爲了在PL/SQL 環境中聲明綁定變量,使用命令VARIABLE。例如:
VARIABLE return_msg VARCHAR2(20)
可以通過SQL*Plus命令中的PRINT 顯示綁定變量的值。例如:
PRINT return_msg
例10:
BEGIN
SELECT (sal*10)+nvl(comm, 0) INTO :result FROM emp
WHERE empno=7844;
END;
--然後再執行
PRINT result
定義記錄表(或索引表)數據類型。它與記錄類型相似,但它是對記錄類型的擴展。它可以處理多行記錄,類似於高級中的二維數組,使得可以在PL/SQL中模仿數據庫中的表。
定義記錄表類型的語法如下:
INDEX BY [BINARY_INTEGER | PLS_INTEGER | VARRAY2];
關鍵字INDEX BY表示創建一個主鍵索引,以便引用記錄表變量中的特定行。
方法 |
描述 |
EXISTS(n) |
如果集合的第n個成員存在,則返回true |
COUNT |
返回已經分配了存儲空間即賦值了的成員數量 |
FIRST LAST |
FIRST:返回成員的最低下標值 LAST: 返回成員的最高下標值 |
PRIOR(n) |
返回下標爲n的成員的前一個成員的下標。如果沒有則返回NULL |
NEXT(N) |
返回下標爲n的成員的後一個成員的下標。如果沒有則返回NULL |
TRIM |
TRIM:刪除末尾一個成員 TRIM(n) :刪除末尾n個成員 |
DELETE |
DELETE:刪除所有成員 DELETE(n) :刪除第n個成員 DELETE(m, n) :刪除從n到m的成員 |
EXTEND |
EXTEND:添加一個null成員 EXTEND(n):添加n個null成員 EXTEND(n,i):添加n個成員,其值與第i個成員相同 |
LIMIT |
返回在varray類型變量中出現的最高下標值 |
例11:
TYPE dept_table_type IS TABLE OF
dept%ROWTYPE INDEX BY BINARY_INTEGER;
my_dname_table dept_table_type;
v_count number(2) :=4;
BEGIN
FOR int IN 1 .. v_count LOOP
SELECT * INTO my_dname_table(int) FROM dept WHERE deptno=int*10;
END LOOP;
FOR int IN my_dname_table.FIRST .. my_dname_table.LAST LOOP
DBMS_OUTPUT.PUT_LINE('Department number: '||my_dname_table(int).deptno);
DBMS_OUTPUT.PUT_LINE('Department name: '|| my_dname_table(int).dname);
END LOOP;
END;
例12:按一維數組使用記錄表
--定義記錄表數據類型
TYPE reg_table_type IS TABLE OF varchar2(25)
INDEX BY BINARY_INTEGER;
--聲明記錄表數據類型的變量
v_reg_table REG_TABLE_TYPE;
BEGIN
v_reg_table(1) := 'Europe';
v_reg_table(2) := 'Americas';
v_reg_table(3) := 'Asia';
v_reg_table(4) := 'Middle East and Africa';
v_reg_table(5) := 'NULL';
DBMS_OUTPUT.PUT_LINE('地區名稱:'||v_reg_table (1)||'、'
||v_reg_table (2)||'、'
||v_reg_table (3)||'、'
||v_reg_table (4));
DBMS_OUTPUT.PUT_LINE('第5個成員的值:'||v_reg_table(5));
END;
例13:按二維數組使用記錄表
--定義記錄表數據類型
TYPE emp_table_type IS TABLE OF employees%ROWTYPE
INDEX BY BINARY_INTEGER;
--聲明記錄表數據類型的變量
v_emp_table EMP_TABLE_TYPE;
BEGIN
SELECT first_name, hire_date, job_id INTO
v_emp_table(1).first_name,v_emp_table(1).hire_date, v_emp_table(1).job_id
FROM employees WHERE employee_id = 177;
SELECT first_name, hire_date, job_id INTO
v_emp_table(2).first_name,v_emp_table(2).hire_date, v_emp_table(2).job_id
FROM employees WHERE employee_id = 178;
DBMS_OUTPUT.PUT_LINE('177僱員名稱:'||v_emp_table(1).first_name
||' 僱傭日期:'||v_emp_table(1).hire_date
||' 崗位:'||v_emp_table(1).job_id);
DBMS_OUTPUT.PUT_LINE('178僱員名稱:'||v_emp_table(2).first_name
||' 僱傭日期:'||v_emp_table(2).hire_date
||' 崗位:'||v_emp_table(2).job_id);
END;
2.5 運算符和表達式(數據定義)
2.5.1 關係運算符
運算符 |
意義 |
= |
等於 |
<> , != , ~= , ^= |
不等於 |
< |
小於 |
> |
大於 |
<= |
小於或等於 |
>= |
大於或等於 |
2.5.2 一般運算符
運算符 |
意義 |
+ |
加號 |
- |
減號 |
* |
乘號 |
/ |
除號 |
:= |
賦值號 |
=> |
關係號 |
.. |
範圍運算符 |
|| |
字符連接符 |
2.5.3 邏輯運算符
運算符 |
意義 |
IS NULL |
是空值 |
BETWEEN AND |
介於兩者之間 |
IN |
在一列值中間 |
AND |
邏輯與 |
OR |
邏輯或 |
NOT |
取返,如IS NOT NULL, NOT IN |
2.6 變量賦值
在PL/SQL編程中,變量賦值是一個值得注意的地方,它的語法如下:
variable := expression ;
variable 是一個PL/SQL變量, expression 是一個PL/SQL 表達式.
2.6.1 字符及數字運算特點
空值加數字仍是空值:NULL + < 數字> = NULL
空值加(連接)字符,結果爲字符:NULL || <字符串> = < 字符串>
2.6.2 BOOLEAN 賦值
布爾值只有TRUE, FALSE及 NULL 三個值。如:
bDone BOOLEAN;
BEGIN
bDone := FALSE;
WHILE NOT bDone LOOP
Null;
END LOOP;
END;
2.6.3 數據庫賦值
數據庫賦值是通過 SELECT語句來完成的,每次執行 SELECT語句就賦值一次,一般要求被賦值的變量與SELECT中的列名要一一對應。如:
例14:
emp_id emp.empno%TYPE :=7788;
emp_name emp.ename%TYPE;
wages emp.sal%TYPE;
BEGIN
SELECT ename, NVL(sal,0) + NVL(comm,0) INTO emp_name, wages
FROM emp WHERE empno = emp_id;
DBMS_OUTPUT.PUT_LINE(emp_name||'----'||to_char(wages));
END;
提示:不能將SELECT語句中的列賦值給布爾變量。
2.6.4 可轉換的類型賦值
l CHAR 轉換爲 NUMBER:
使用 TO_NUMBER 函數來完成字符到數字的轉換,如:
v_total := TO_NUMBER('100.0') + sal;
l NUMBER 轉換爲CHAR:
使用 TO_CHAR函數可以實現數字到字符的轉換,如:
v_comm := TO_CHAR('123.45') || '元' ;
l 字符轉換爲日期:
使用 TO_DATE函數可以實現 字符到日期的轉換,如:
v_date := TO_DATE('2001.07.03','yyyy.mm.dd');
l 日期轉換爲字符
使用 TO_CHAR函數可以實現日期到字符的轉換,如:
v_to_day := TO_CHAR(SYSDATE, 'yyyy.mm.dd hh24:mi:ss') ;
2.7 變量作用範圍及可見性
在PL/SQL編程中,如果在變量的定義上沒有做到統一的話,可能會隱藏一些危險的錯誤,這樣的原因主要是變量的作用範圍所致。變量的作用域是指變量的有效作用範圍,與其它高級語言類似,PL/SQL的變量作用範圍特點是:
l 變量的作用範圍是在你所引用的程序單元(塊、子程序、包)內。即從聲明變量開始到該塊的結束。
l 一個變量(標識)只能在你所引用的塊內是可見的。
l 當一個變量超出了作用範圍,PL/SQL引擎就釋放用來存放該變量的空間(因爲它可能不用了)。
l 在子塊中重新定義該變量後,它的作用僅在該塊內。
例15:
註釋
Emess char(80);
BEGIN
DECLARE
V1 NUMBER(4);
BEGIN
SELECT empno INTO v1 FROM emp WHERE LOWER(job)='president';
DBMS_OUTPUT.PUT_LINE(V1);
EXCEPTION
When TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE ('More than one president');
END;
DECLARE
V1 NUMBER(4);
BEGIN
SELECT empno INTO v1 FROM emp WHERE LOWER(job)='manager';
EXCEPTION
When TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE ('More than one manager');
END;
EXCEPTION
When others THEN
Emess:=substr(SQLERRM,1,80);
DBMS_OUTPUT.PUT_LINE(emess);
END;
2.8
在PL/SQL裏,可以使用兩種符號來寫註釋,即:
l 使用雙 ‘-‘ ( 減號) 加註釋
PL/SQL允許用 – 來寫註釋,它的作用範圍是只能在一行有效。如:
V_Sal NUMBER(12,2); -- 人員的工資變量。
l 使用 /* */ 來加一行或多行註釋,如:
/***********************************************/
/* 文件名: department_salary.sql */
/* 作 者: EricHu */
/* 時 間: 2011-5-9 */
/***********************************************/
提示:被解釋後存放在數據庫中的 PL/SQL 程序,一般系統自動將程序頭部的註釋去掉。只有在 PROCEDURE 之後的註釋才被保留;另外程序中的空行也自動被去掉。
2.9 簡單例子
2.9.1 簡單數據插入例子
例16:
/* 文件名: test.sql */
/* 說 明:
一個簡單的插入測試,無實際應用。*/
/* 作 者: EricHu */
/* 時 間: 2011-5-9 */
/***********************************************/
DECLARE
v_ename VARCHAR2(20) := 'Bill';
v_sal NUMBER(7,2) :=1234.56;
v_deptno NUMBER(2) := 10;
v_empno NUMBER(4) := 8888;
BEGIN
INSERT INTO emp ( empno, ename, JOB, sal, deptno , hiredate )
VALUES (v_empno, v_ename, 'Manager', v_sal, v_deptno,
TO_DATE('1954.06.09','yyyy.mm.dd') );
COMMIT;
END;
例17:
/* 文件名: test_deletedata.sql */
/* 說 明:
簡單的刪除例子,不是實際應用。 */
/* 作 者: EricHu */
/* 時 間: 2011-5-9 */
/***********************************************/
DECLARE
v_ename VARCHAR2(20) := 'Bill';
v_sal NUMBER(7,2) :=1234.56;
v_deptno NUMBER(2) := 10;
v_empno NUMBER(4) := 8888;
BEGIN
INSERT INTO emp ( empno, ename, JOB, sal, deptno , hiredate )
VALUES ( v_empno, v_ename, ‘Manager’, v_sal, v_deptno,
TO_DATE(’1954.06.09’,’yyyy.mm.dd’) );
COMMIT;
END;
DECLARE
v_empno number(4) := 8888;
BEGIN
DELETE FROM emp WHERE empno=v_empno;
COMMIT;
END;
© 2011 EricHu
原創作品,轉貼請註明作者和出處,留此信息。
------------------------------------------------
cnBlobs:http://www.cnblogs.com/huyong/
CSDN:http://blog.csdn.NET/chinahuyong
作者:EricHu(DB、C/S、B/S、WebService、WCF、PM等)
出處:http://www.cnblogs.com/huyong/
Q Q:80368704 E-Mail: [email protected]
本博文歡迎大家瀏覽和轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,在『參考』的文章中,我會表明參考的文章來源,尊重他人版權。若您發現我侵犯了您的版權,請及時與我聯繫。
更多文章請看 [置頂]索引貼——(不斷更新中)