先來(lái)看一下默認(rèn)的連接SQL Server數(shù)據(jù)庫(kù)配置
<connectionStrings>
?? <add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
SqlConnectionStringBuilder實(shí)例化時(shí)需要使用connectionString。如:SqlConnectionStringBuild builder = new SqlConnectionStringBuild(connectionString);
一、Data Source
SqlConnectionStringBuilder的DataSource屬性,對(duì)應(yīng)connectionString中的Data Source,“Data Source”可以由下列字符串代替:“Server”,“Address”,“Addr”和“Network Address”。
Data Source=.\SQLExpress也可以寫(xiě)成這樣Data Source=(local)\SQLExpress。
二、Integrated Security
SqlConnectionStringBuilder 的 IntegratedSecurity 屬性,對(duì)應(yīng) connectionString 中的I ntegrated Security,“Integrated Security”可以寫(xiě)成“trusted_connection”。
為 True 時(shí),使用當(dāng)前的 Windows 帳戶憑據(jù)進(jìn)行身份驗(yàn)證,為 False 時(shí),需要在連接中指定用戶 ID 和密碼。可識(shí)別的值為 True、False、Yes、No 以及與 True 等效的 SSPI。
如果沒(méi)有些則必須寫(xiě)上 uid=sa;pwd=123 之類的設(shè)置“uid”也可使用“User ID”,“pwd”也可換為“PassWord”。
SSPI:Microsoft安全支持提供器接口(SSPI)是定義得較全面的公用API,用來(lái)獲得驗(yàn)證、信息完整性、信息隱私等集成安全服務(wù),以及用于所有分布式應(yīng)用程序協(xié)議的安全方面的服務(wù)。
應(yīng)用程序協(xié)議設(shè)計(jì)者能夠利用該接口獲得不同的安全性服務(wù)而不必修改協(xié)議本身。
三、AttachDBFilename
SqlConnectionStringBuilder 的 AttachDBFilename 屬性,對(duì)應(yīng) connectionString 中的 AttachDBFilename,“AttachDBFilename”可以寫(xiě)成“extended properties”,“initial file name”。
AttachDbFileName 屬性指定連接打開(kāi)的時(shí)候動(dòng)態(tài)附加到服務(wù)器上的數(shù)據(jù)庫(kù)文件的位置。
這個(gè)屬性可以接受數(shù)據(jù)庫(kù)的完整路徑和相對(duì)路徑(例如使用|DataDirectory|語(yǔ)法),在運(yùn)行時(shí)這個(gè)路徑會(huì)被應(yīng)用程序的 App_Data 目錄所代替。
四、User Instance
SqlConnectionStringBuilder 的 UserInstance 屬性,對(duì)應(yīng) connectionString 中的 User Instance ,該值指示是否將連接從默認(rèn)的 SQL Server 實(shí)例重定向到在調(diào)用方帳戶之下運(yùn)行并且在運(yùn)行時(shí)啟動(dòng)的實(shí)例。
UserInstance=true 時(shí),SQLServerExpress 為了把數(shù)據(jù)庫(kù)附加到新的實(shí)例,建立一個(gè)新的進(jìn)程,在打開(kāi)連接的用戶身份下運(yùn)行。
在 ASP.NET 應(yīng)用程序中,這個(gè)用戶是本地的 ASPNET 帳號(hào)或默認(rèn)的 NetworkService,這依賴于操作系統(tǒng)。
為了安全地附加非系統(tǒng)管理員帳號(hào)(例如ASP.NET帳號(hào))提供的數(shù)據(jù)庫(kù)文件,建立一個(gè)獨(dú)立的 SQLServer 用戶實(shí)例是必要的。
五、Initial Catalog 等同于 Database。
六、providerName 指定值“System.Data.OracleClient”,該值指定 ASP.NET 在使用此連接字符串進(jìn)行連接時(shí)應(yīng)使用 ADO.NET System.Data.OracleClient 提供程序。
PS:
DataDirectory是什么?
asp.net 2.0有一個(gè)特殊目錄app_data,通常Sql Server 2005 express數(shù)據(jù)文件就放在這個(gè)目錄,相應(yīng)的數(shù)據(jù)庫(kù)連接串就是:
connectionString="…… data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|data.mdf;User Instance=true"
這里有一個(gè)DataDirectory的宏,它表示什么意義呢?
DataDirectory是表示數(shù)據(jù)庫(kù)路徑的替換字符串。由于無(wú)需對(duì)完整路徑進(jìn)行硬編碼,DataDirectory 簡(jiǎn)化了項(xiàng)目的共享和應(yīng)用程序的部署。例如,無(wú)需使用以下連接字符串:
"Data Source= c:\program files\MyApp\app_data\Mydb.mdf"
通過(guò)使用|DataDirectory|(包含在如下所示的豎線中),即可具有以下連接字符串:
"Data Source = |DataDirectory|\Mydb.mdf" 。
不僅僅是Sql server 2005 express中使用,也可以在其它的文件數(shù)據(jù)庫(kù)中使用,例如Sqllite數(shù)據(jù)庫(kù)文件的連接字符串:
<add name="DefaultDB"
connectionString="DriverClass=NHibernate.Driver.SQLite20Driver;Dialect=NHibernate.Dialect.SQLiteDialect;Data Source=|DataDirectory|\data.db3" />
---------------------------------------??? 附加一些連接語(yǔ)句例子??? ---------------------------------------
<--普通例子1-->
<configuration>
<connectionStrings>
??? <add name="Sales" providerName="System.Data.SqlClient" connectionString="server=myserver;database=Products;uid=salesUser;pwd=sellMoreProducts" />
??? <add name="NorthWind" providerName="System.Data.SqlClient" connectionString="server=.;database=NorthWind;Integrated Security=SSPI" />
</connectionStrings>
</configuration>
<--普通例子2-->
<configuration>
<connectionStrings>
??? <add name="NorthWind" connectionString="Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=da;Data Source=bar" />
</configuration>
----------------------------------------------------------------------------------------------------------
<connectionStrings>
?? <add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Initial Catalog=NorthWind;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
<--也可寫(xiě)為-->
<connectionStrings>
?? <add name="LocalSqlServer" connectionString="Server=.\SQLExpress;Database=NorthWind;Integrated Security=Yes" providerName="System.Data.SqlClient" />
</connectionStrings>
----------------------------------------------------------------------------------------------------------
<configuration>
<connectionStrings>
??? <add name="DB2005_2"
??? providerName="System.Data.SqlClient"
??? connectionString="Data Source=.;Initial Catalog=Northwind;User ID=dbtester;Password=zhi;Trusted_Connection=False;Connect Timeout=30;Min Pool Size=16;Max Pool Size=100"/>
??? <add name="DB2005_1"
??? providerName="System.Data.SqlClient"
??? connectionString="Server=.;Database=Northwind;User ID=dbtester;Password=zhi;Trusted_Connection=False;Connect Timeout=30;Min Pool Size=16;Max Pool Size=100"/>
??? <add name="Northword2000"
??? providerName="System.Data.SqlClient"
??? connectionString="Initial Catalog=Northwind;User ID=dbtester;PassWord=zhi;Persist Security Info=false;Data Source=(local);Connect Timeout=30;Min Pool Size=16;Max Pool Size=100;"/>
??? <add name="SQLExp"
?????? providerName="System.Data.SqlClient"
?????? connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\northwnd1.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/>
???
??? <add name="Oracle"
????? connectionString="Data Source=TEST;User ID=sa;Password=sa;"
????? providerName="System.Data.OracleClient" />
??? <add name="oleconn"
?????? providerName="System.Data.OleDb"
?????? connectionString="Provider=Microsoft.Jet.OleDb.4.0;Data Source=|DataDirectory|northwind.mdb"/>
??? <add name="MySql"
??? providerName="MySql.Data.MySqlClient"
??? connectionString="Server=172.29.131.27;Port=3311;DataBase=comctl;Persist Security Info=False;User ID=root;Password=123456;Allow Zero Datetime=true;" />
</connectionStrings>
??? <system.data>
??????? <DbProviderFactories>
??????????? <add name="MySQL Data Provider"
???????????????? invariant="MySql.Data.MySqlClient"
???????????????? description=".Net Framework Data Provider for MySQL"
???????????????? type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
??????? </DbProviderFactories>
??? </system.data>
</configuration>
======================================????? 可以保存為(以下轉(zhuǎn)自他處).cs????? ======================================
using System.Data.SqlClient;
using System.Configuration;
public class Class1
{
??? public Class1()
??? {
??????? //Persist Security Info如果數(shù)據(jù)庫(kù)連接成功后不再需要連接的密碼,建議False
??????? //string sql2000 = "Initial Catalog=Northwind;User ID=dbtester;PassWord=zhi;Persist Security Info=false;Data Source=(local);Connect Timeout=30;Min Pool Size=16;Max Pool Size=100;";
??????? //string sql2000 = "Initial Catalog=Northwind;User ID=sa;PassWord=5;Persist Security Info=false;Data Source=.";
??????? //string sql2000 = "Initial Catalog=Northwind;User ID=sa;PassWord=5;Persist Security Info=false;Data Source=newtime";
??????? string source = "server=(local);integrated security=SSPI;database=Northwind";
??????? string expressSource = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\northwnd.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
??????? //Integrated Security采用windows的集成身份驗(yàn)證,integraged?? Security=SSPI;
??????? //Integrated Security=SSPI 這個(gè)表示以當(dāng)前WINDOWS系統(tǒng)用戶身去登錄SQL SERVER服務(wù)器,如果SQL SERVER服務(wù)器不支持這種方式登錄時(shí),就會(huì)出錯(cuò)
??????? //表示你的連接安全驗(yàn)證方式,可用trusted_connection=yes取代
??????? //Integrated Security 為 True。用戶實(shí)例僅與集成安全性一起使用,帶有用戶名和密碼的 SQL Server 用戶不起作用。
??????? //string source3 = @"Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog= pubs;UserID=sa;Password=asdasd;";
??????? //(DBMSSOCN=TCP/IP instead of Named Pipes, at the end of the Data Source is the port to use (1433 is the default))
??????? //Standard Security:
??????? string source4 = "Data Source=Aron1;Initial Catalog= pubs;UserId=sa;Password=asdasd;";
??????? string source5 = "Server=Aron1;Database=pubs;UserID=sa;Password=asdasd;Trusted_Connection=False";
??????? //Trusted_Connection 'false' 當(dāng)為 false 時(shí),將在連接中指定用戶 ID 和密碼。當(dāng)為 true 時(shí),將使用當(dāng)前的 Windows 帳戶憑據(jù)進(jìn)行身份驗(yàn)證。
??????? //可識(shí)別的值為 true、false、yes、no 以及與 true 等效的 sspi(強(qiáng)烈推薦)。所以一定要設(shè)置Trusted_Connection= false,以防被別人"登錄"、"注入語(yǔ)句"等
??????? string source6 = "Data Source=Aron1;Initial Catalog=pubs;Integrated Security=SSPI;";
??????? string source7 = "Server=Aron1;Database=pubs;Trusted_Connection=True;";
??????? //(use serverName\instanceName as Data Source to use an specifik SQLServer instance, only SQLServer2000)
??????? //Integrated?? Security或Trusted_Connection?? 'false'?? 當(dāng)為?? false?? 時(shí),
??????? //將在連接中指定用戶?? ID?? 和密碼。當(dāng)為?? true?? 時(shí),將使用當(dāng)前的?? Windows?? 帳戶憑據(jù)進(jìn)行身份驗(yàn)證
??????? //VS2003:string connStr=System.Configuration.ConfigurationSettings.AppSettings["SQLCONNECTIONSTRING"];2003中用的
??????? //VS2005:string connStr=System.Configuration.ConfigurationManager.ConnectionStrings["SQLCONNECTIONSTRING"].ToString();2005-8中用
??????? System.Configuration.ConnectionStringSettings i = System.Configuration.ConfigurationManager.ConnectionStrings["Northword2000"];
??? }
}
?
1. 選用適合的ORACLE優(yōu)化器
ORACLE的優(yōu)化器共有3種:
a. RULE (基于規(guī)則) b. COST (基于成本) c. CHOOSE (選擇性)
設(shè)置缺省的優(yōu)化器,可以通過(guò)對(duì)init.ora文件中OPTIMIZER_MODE參數(shù)的各種聲明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你當(dāng)然也在SQL句級(jí)或是會(huì)話(session)級(jí)對(duì)其進(jìn)行覆蓋.
為了使用基于成本的優(yōu)化器(CBO, Cost-Based Optimizer) , 你必須經(jīng)常運(yùn)行analyze 命令,以增加數(shù)據(jù)庫(kù)中的對(duì)象統(tǒng)計(jì)信息(object statistics)的準(zhǔn)確性.
如果數(shù)據(jù)庫(kù)的優(yōu)化器模式設(shè)置為選擇性(CHOOSE),那么實(shí)際的優(yōu)化器模式將和是否運(yùn)行過(guò)analyze命令有關(guān). 如果table已經(jīng)被analyze過(guò), 優(yōu)化器模式將自動(dòng)成為CBO , 反之,數(shù)據(jù)庫(kù)將采用RULE形式的優(yōu)化器.
在缺省情況下,ORACLE采用CHOOSE優(yōu)化器, 為了避免那些不必要的全表掃描(full table scan) , 你必須盡量避免使用CHOOSE優(yōu)化器,而直接采用基于規(guī)則或者基于成本的優(yōu)化器.
2. 訪問(wèn)Table的方式
ORACLE 采用兩種訪問(wèn)表中記錄的方式:
a. 全表掃描
全表掃描就是順序地訪問(wèn)表中每條記錄. ORACLE采用一次讀入多個(gè)數(shù)據(jù)塊(database block)的方式優(yōu)化全表掃描.
b. 通過(guò)ROWID訪問(wèn)表
你可以采用基于ROWID的訪問(wèn)方式情況,提高訪問(wèn)表的效率, ,
ROWID包含了表中記錄的物理位置信息..ORACLE采用索引(INDEX)實(shí)現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置(ROWID)之間的聯(lián)系.
通常索引提供了快速訪問(wèn)ROWID的方法,因此那些基于索引列的查詢就可以得到性能上的提高.
3. 共享SQL語(yǔ)句
為了不重復(fù)解析相同的SQL語(yǔ)句,在第一次解析之后, ORACLE將SQL語(yǔ)句存放在內(nèi)存中.這塊位于系統(tǒng)全局區(qū)域SGA(system
global area)的共享池(shared buffer pool)中的內(nèi)存可以被所有的數(shù)據(jù)庫(kù)用戶共享.
因此,當(dāng)你執(zhí)行一個(gè)SQL語(yǔ)句(有時(shí)被稱為一個(gè)游標(biāo))時(shí),如果它 和之前的執(zhí)行過(guò)的語(yǔ)句完全相同,
ORACLE就能很快獲得已經(jīng)被解析的語(yǔ)句以及最好的執(zhí)行路徑. ORACLE的這個(gè)功能大大地提高了SQL的執(zhí)行性能并節(jié)省了內(nèi)存的使用.
可惜的是ORACLE只對(duì)簡(jiǎn)單的表提供高速緩沖(cache buffering) ,這個(gè)功能并不適用于多表連接查詢.
數(shù)據(jù)庫(kù)管理員必須在init.ora中為這個(gè)區(qū)域設(shè)置合適的參數(shù),當(dāng)這個(gè)內(nèi)存區(qū)域越大,就可以保留更多的語(yǔ)句,當(dāng)然被共享的可能性也就越大了.
當(dāng)你向ORACLE 提交一個(gè)SQL語(yǔ)句,ORACLE會(huì)首先在這塊內(nèi)存中查找相同的語(yǔ)句.
這里需要注明的是,ORACLE對(duì)兩者采取的是一種嚴(yán)格匹配,要達(dá)成共享,SQL語(yǔ)句必須完全相同(包括空格,換行等).
共享的語(yǔ)句必須滿足三個(gè)條件:
A. 字符級(jí)的比較:
當(dāng)前被執(zhí)行的語(yǔ)句和共享池中的語(yǔ)句必須完全相同.
例如:
SELECT * FROM EMP;
和下列每一個(gè)都不同
SELECT * from EMP;
Select * From Emp;
SELECT * FROM EMP;
B. 兩個(gè)語(yǔ)句所指的對(duì)象必須完全相同:
例如:
用戶 對(duì)象名 如何訪問(wèn)
Jack sal_limit private synonym
Work_city public synonym
Plant_detail public synonym
Jill sal_limit private synonym
Work_city public synonym
Plant_detail table owner
考慮一下下列SQL語(yǔ)句能否在這兩個(gè)用戶之間共享.
SQL能否共享,原因
select max(sal_cap) from sal_limit;
不能。每個(gè)用戶都有一個(gè)private synonym - sal_limit , 它們是不同的對(duì)象
select count(*0 from work_city where sdesc like 'NEW%';
能。兩個(gè)用戶訪問(wèn)相同的對(duì)象public synonym - work_city
select a.sdesc,b.location from work_city a , plant_detail b where a.city_id = b.city_id
不能。用戶jack 通過(guò)private synonym訪問(wèn)plant_detail 而jill 是表的所有者,對(duì)象不同.
C. 兩個(gè)SQL語(yǔ)句中必須使用相同的名字的綁定變量(bind variables)
例如:
第一組的兩個(gè)SQL語(yǔ)句是相同的(可以共享),而第二組中的兩個(gè)語(yǔ)句是不同的(即使在運(yùn)行時(shí),賦于不同的綁定變量相同的值)
a.
select pin , name from people where pin = :blk1.pin;
select pin , name from people where pin = :blk1.pin;
b.
select pin , name from people where pin = :blk1.ot_ind;
select pin , name from people where pin = :blk1.ov_ind;
4. 選擇最有效率的表名順序(只在基于規(guī)則的優(yōu)化器中有效)
ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫(xiě)在最后的表(基礎(chǔ)表 driving
table)將被最先處理. 在FROM子句中包含多個(gè)表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表.當(dāng)ORACLE處理多個(gè)表時(shí),
會(huì)運(yùn)用排序及合并的方式連接它們.首先,掃描第一個(gè)表(FROM子句中最后的那個(gè)表)并對(duì)記錄進(jìn)行派序,然后掃描第二個(gè)表(FROM子句中最后第二個(gè)
表),最后將所有從第二個(gè)表中檢索出的記錄與第一個(gè)表中合適記錄進(jìn)行合并.
例如:
表 TAB1 16,384 條記錄
表 TAB2 1 條記錄
選擇TAB2作為基礎(chǔ)表 (最好的方法)
select count(*) from tab1,tab2 執(zhí)行時(shí)間0.96秒
選擇TAB2作為基礎(chǔ)表 (不佳的方法)
select count(*) from tab2,tab1 執(zhí)行時(shí)間26.09秒
如果有3個(gè)以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎(chǔ)表, 交叉表是指那個(gè)被其他表所引用的表.
例如:
EMP表描述了LOCATION表和CATEGORY表的交集.
SELECT *
FROM LOCATION L ,
CATEGORY C,
EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
將比下列SQL更有效率
SELECT *
FROM EMP E ,
LOCATION L ,
CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2000
5. WHERE子句中的連接順序.
ORACLE采用自下而上的順序解析WHERE子句,根據(jù)這個(gè)原理,表之間的連接必須寫(xiě)在其他WHERE條件之前, 那些可以過(guò)濾掉最大數(shù)量記錄的條件必須寫(xiě)在WHERE子句的末尾.
例如: (低效,執(zhí)行時(shí)間156.3秒)
SELECT …
FROM EMP E
WHERE SAL > 50000
AND JOB = ‘MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO);
(高效,執(zhí)行時(shí)間10.6秒)
SELECT …
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = ‘MANAGER';
6. SELECT子句中避免使用 ‘ * ‘
當(dāng)你想在SELECT子句中列出所有的COLUMN時(shí),使用動(dòng)態(tài)SQL列引用 ‘*'
是一個(gè)方便的方法.不幸的是,這是一個(gè)非常低效的方法. 實(shí)際上,ORACLE在解析的過(guò)程中, 會(huì)將'*' 依次轉(zhuǎn)換成所有的列名,
這個(gè)工作是通過(guò)查詢數(shù)據(jù)字典完成的, 這意味著將耗費(fèi)更多的時(shí)間.
7. 減少訪問(wèn)數(shù)據(jù)庫(kù)的次數(shù)
當(dāng)執(zhí)行每條SQL語(yǔ)句時(shí), ORACLE在內(nèi)部執(zhí)行了許多工作: 解析SQL語(yǔ)句, 估算索引的利用率, 綁定變量 , 讀數(shù)據(jù)塊等等. 由此可見(jiàn), 減少訪問(wèn)數(shù)據(jù)庫(kù)的次數(shù) , 就能實(shí)際上減少ORACLE的工作量.
例如, 以下有三種方法可以檢索出雇員號(hào)等于0342或0291的職員.
方法1 (最低效)
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 342;
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 291;
方法2 (次低效)
DECLARE
CURSOR C1 (E_NO NUMBER) IS
SELECT EMP_NAME,SALARY,GRADE
FROM EMP
WHERE EMP_NO = E_NO;
BEGIN
OPEN C1(342);
FETCH C1 INTO …,..,.. ;
…..
OPEN C1(291);
FETCH C1 INTO …,..,.. ;
CLOSE C1;
END;
方法3 (高效)
SELECT A.EMP_NAME , A.SALARY , A.GRADE,
B.EMP_NAME , B.SALARY , B.GRADE
FROM EMP A,EMP B
WHERE A.EMP_NO = 342
AND B.EMP_NO = 291;
注意:
在SQL*Plus , SQL*Forms和Pro*C中重新設(shè)置ARRAYSIZE參數(shù), 可以增加每次數(shù)據(jù)庫(kù)訪問(wèn)的檢索數(shù)據(jù)量 ,建議值為200。
8. 使用DECODE函數(shù)來(lái)減少處理時(shí)間
使用DECODE函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表.
例如:
SELECT COUNT(*),SUM(SAL) FROM EMP
WHERE DEPT_NO = 0020
AND ENAME LIKE ‘SMITH%';
SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT_NO = 0030
AND ENAME LIKE ‘SMITH%';
你可以用DECODE函數(shù)高效地得到相同結(jié)果
SELECT COUNT(DECODE(DEPT_NO,0020,'X',NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO,0030,'X',NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,
SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL
FROM EMP WHERE ENAME LIKE ‘SMITH%';
類似的,DECODE函數(shù)也可以運(yùn)用于GROUP BY 和ORDER BY子句中.
9. 整合簡(jiǎn)單,無(wú)關(guān)聯(lián)的數(shù)據(jù)庫(kù)訪問(wèn)
如果你有幾個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)查詢語(yǔ)句,你可以把它們整合到一個(gè)查詢中(即使它們之間沒(méi)有關(guān)系)
例如:
SELECT NAME FROM EMP
WHERE EMP_NO = 1234;
SELECT NAME FROM DPT
WHERE DPT_NO = 10 ;
SELECT NAME FROM CAT
WHERE CAT_TYPE = ‘RD';
上面的3個(gè)查詢可以被合并成一個(gè):
SELECT E.NAME , D.NAME , C.NAME FROM CAT C , DPT D , EMP E,DUAL X
WHERE NVL(‘X',X.DUMMY) = NVL(‘X',E.ROWID(+))
AND NVL(‘X',X.DUMMY) = NVL(‘X',D.ROWID(+))
AND NVL(‘X',X.DUMMY) = NVL(‘X',C.ROWID(+))
AND E.EMP_NO(+) = 1234
AND D.DEPT_NO(+) = 10
AND C.CAT_TYPE(+) = ‘RD';
(譯者按: 雖然采取這種方法,效率得到提高,但是程序的可讀性大大降低,所以讀者 還是要權(quán)衡之間的利弊)
10. 刪除重復(fù)記錄
最高效的刪除重復(fù)記錄方法 ( 因?yàn)槭褂昧薘OWID)
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO);
11. 用TRUNCATE替代DELETE
當(dāng)刪除表中的記錄時(shí),在通常情況下, 回滾段(rollback segments ) 用來(lái)存放可以被恢復(fù)的信息.
如果你沒(méi)有COMMIT事務(wù),ORACLE會(huì)將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài)(準(zhǔn)確地說(shuō)是恢復(fù)到執(zhí)行刪除命令之前的狀況) ,而當(dāng)運(yùn)用TRUNCATE時(shí),
回滾段不再存放任何可被恢復(fù)的信息.當(dāng)命令運(yùn)行后,數(shù)據(jù)不能被恢復(fù).因此很少的資源被調(diào)用,執(zhí)行時(shí)間也會(huì)很短。(注:
TRUNCATE只在刪除全表適用,TRUNCATE是DDL不是DML)
12. 盡量多使用COMMIT
只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會(huì)因?yàn)镃OMMIT所釋放的資源而減少:
COMMIT所釋放的資源:
a. 回滾段上用于恢復(fù)數(shù)據(jù)的信息.
b. 被程序語(yǔ)句獲得的鎖
c. redo log buffer 中的空間
d. Oracle為管理上述3種資源中的內(nèi)部花費(fèi)
(注:在使用COMMIT時(shí)必須要注意到事務(wù)的完整性,現(xiàn)實(shí)中效率和事務(wù)完整性往往是魚(yú)和熊掌不可得兼)
如果DECODE取值為NULL,SUM(NULL)的值是NULL -->如果所有的值都是NULL , SUM(NULL) = NULL 但是只要有一個(gè)值不是NULL,SUM() <> NULL 所以原SQL應(yīng)該沒(méi)有什么邏輯上的問(wèn)題
關(guān)于第八點(diǎn)的個(gè)人看法:如果DECODE取值為NULL,SUM(NULL)的值是NULL,不會(huì)正常求和的。可以改成如下所示就好了:
SELECT COUNT(DECODE(DEPT_NO,0020,'X',NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO,0030,'X',NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO,0020,SAL,0)) D0020_SAL,
SUM(DECODE(DEPT_NO,0030,SAL,0)) D0030_SAL FROM EMP WHERE ENAME LIKE
‘SMITH%';
#1 定義了兩個(gè)輸出端
log4j.rootLogger = INFO, A1, A2,A3
#2 定義A1輸出到控制器
log4j.appender.A1 = org.apache.log4j.ConsoleAppender
#3 定義A1的布局模式為PatternLayout
log4j.appender.A1.layout = org.apache.log4j.PatternLayout
#4 定義A1的輸出格式
log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c - %m%n
#5 定義A2輸出到文件
log4j.appender.A2 = org.apache.log4j.RollingFileAppender
#6 定義A2要輸出到哪一個(gè)文件
log4j.appender.A2.File = F:\\nepalon\\classes\\example3.log
#7 定義A2的輸出文件的最大長(zhǎng)度
log4j.appender.A2.MaxFileSize = 1KB
#8 定義A2的備份文件數(shù)
log4j.appender.A2.MaxBackupIndex = 3
#9 定義A2的布局模式為PatternLayout
log4j.appender.A2.layout = org.apache.log4j.PatternLayout
#10 定義A2的輸出格式
log4j.appender.A2.layout.ConversionPattern = %d{yyyy-MM-dd hh:mm:ss}:%p %t %c - %m%n
#11區(qū) 定義A3輸出到數(shù)據(jù)庫(kù)
log4j.appender.A3 = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.A3.BufferSize = 40
log4j.appender.A3.Driver = com.microsoft.jdbc.sqlserver.SQLServerDriver
log4j.appender.A3.URL = jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=nepalon
log4j.appender.A3.User = sa
log4j.appender.A3.Password =
log4j.appender.A3.layout = org.apache.log4j.PatternLayout
log4j.appender.A3.layout.ConversionPattern = INSERT INTO log4j
(createDate, thread, priority, category, message) values(getdate(),
'%t', '%-5p', '%c', '%m')