SQL語句如何處理
在調整之前我們需要了解一些背景知識,只有知道這些背景知識,我們才能更好的去調整sql語句。
本節介紹了SQL語句處理的基本過程,主要包括: · 查詢語句處理 · DML語句處理(insert, update, delete) · DDL 語句處理(create 。 。
, drop 。
, alter 。
, ) · 事務控制(commit, rollback) SQL 語句的執行過程(SQL Statement Execution) 在某些情況下,Oracle運行sql的過程可能與下面列出的各個階段的順序有所不同。 如DEFINE階段可能在FETCH階段之前,這主要依賴你如何書寫代碼。
對許多oracle的工具來說,其中某些階段會自動執行。絕大多數用戶不需要關心各個階段的細節問題,然而,知道執行的各個階段還是有必要的,這會幫助你寫出更高效的SQL語句來,而且還可以讓你猜測出性能差的SQL語句主要是由于哪一個階段造成的,然后我們針對這個具體的階段,找出解決的辦法。
DML語句的處理 本節給出一個例子來說明在DML語句處理的各個階段到底發生了什么事情。假設你使用Pro*C程序來為指定部門的所有職員增加工資。
程序已經連到正確的用戶,你可以在你的程序中嵌入如下的SQL語句: EXEC SQL UPDATE employees SET salary = 1。 10 * salary WHERE department_id = :var_department_id; var_department_id是程序變量,里面包含部門號,我們要修改該部門的職員的工資。
當這個SQL語句執行時,使用該變量的值。 每種類型的語句都需要如下階段: · 第1步: Create a Cursor 創建游標 · 第2步: Parse the Statement 分析語句 · 第5步: Bind Any Variables 綁定變量 · 第7步: Run the Statement 運行語句 · 第9步: Close the Cursor 關閉游標 如果使用了并行功能,還會包含下面這個階段: · 第6步: Parallelize the Statement 并行執行語句 如果是查詢語句,則需要以下幾個額外的步驟,如圖 3所示: · 第3步: Describe Results of a Query 描述查詢的結果集 · 第4步: Define Output of a Query 定義查詢的輸出數據 · 第8步: Fetch Rows of a Query 取查詢出來的行 下面具體說一下每一步中都發生了什么事情:。
第1步: 創建游標(Create a Cursor) 由程序接口調用創建一個游標(cursor)。任何SQL語句都會創建它,特別在運行DML語句時,都是自動創建游標的,不需要開發人員干預。
多數應用中,游標的創建是自動的。然而,在預編譯程序(pro*c)中游標的創建,可能是隱含的,也可能顯式的創建。
在存儲過程中也是這樣的。 第2步:分析語句(Parse the Statement) 在語法分析期間,SQL語句從用戶進程傳送到Oracle,SQL語句經語法分析后,SQL語句本身與分析的信息都被裝入到共享SQL區。
在該階段中,可以解決許多類型的錯誤。 語法分析分別執行下列操作: *翻譯SQL語句,驗證它是合法的語句,即書寫正確 *實現數據字典的查找,以驗證是否符合表和列的定義 *在所要求的對象上獲取語法分析鎖,使得在語句的語法分析過程中不改變這些對象的定義 *驗證為存取所涉及的模式對象所需的權限是否滿足 *決定此語句最佳的執行計劃 *將它裝入共享SQL區 *對分布的語句來說,把語句的全部或部分路由到包含所涉及數據的遠程節點 以上任何一步出現錯誤,都將導致語句報錯,中止執行。
只有在共享池中不存在等價SQL語句的情況下,才對SQL語句作語法分析。在這種情況下,數據庫內核重新為該語句分配新的共享SQL區,并對語句進行語法分析。
進行語法分析需要耗費較多的資源,所以要盡量避免進行語法分析,這是優化的技巧之一。 語法分析階段包含了不管此語句將執行多少次,而只需分析一次的處理要求。
Oracle只對每個SQL語句翻譯一次,在以后再次執行該語句時,只要該語句還在共享SQL區中,就可以避免對該語句重新進行語法分析,也就是此時可以直接使用其對應的執行計劃對數據進行存取。這主要是通過綁定變量(bind variable)實現的,也就是我們常說的共享SQL,后面會給出共享SQL的概念。
雖然語法分析驗證了SQL語句的正確性,但語法分析只能識別在SQL語句執行之前所能發現的錯誤(如書寫錯誤、權限不足等)。因此,有些錯誤通過語法分析是抓不到的。
例如,在數據轉換中的錯誤或在數據中的錯(如企圖在主鍵中插入重復的值)以及死鎖等均是只有在語句執行階段期間才能遇到和報告的錯誤或情況。 查詢語句的處理 查詢與其它類型的SQL語句不同,因為在成功執行后作為結果將返回數據。
其它語句只是簡單地返回成功或失敗,而查詢則能返回一行或許多行數據。查詢的結果均采用表格形式,結果行被一次一行或者批量地被檢索出來。
從這里我們可以得知批量的fetch數據可以降低網絡開銷,所以批量的fetch也是優化的技巧之一。 有些問題只與查詢處理相關,查詢不僅僅指SELECT語句,同樣也包括在其它SQL語句中的隱含查詢。
例如,下面的每個語句都需要把查詢作為它執行的一部分: INSERT INTO table SELECT。
。 UPDATE table SET x = y WHERE。
。
DELETE FROM table WHERE。
。 CREATE table AS SELECT。
具體來說,查詢 · 要求讀一致性 · 可能使用回滾段。
一條sql的整個過程是怎樣的
SQL語句執行過程詳解 一、SQL語句執行原理:第一步:客戶端把語句發給服務器端執行當我們在客戶端執行 select 語句時,客戶端會把這條 SQL 語句發送給服務器端,讓服務器端的進程來處理這語句。
也就是說,Oracle 客戶端是不會做任何的操作,他的主要任務就是把客戶端產生的一些 SQL 語句發送給服務器端。雖然在客戶端也有一個數據庫進程,但是,這個進程的作用跟服務器上的進程作用事不相同的。
服務器上的數據庫進程才會對SQL 語句進行相關的處理。不過,有個問題需要說明,就是客戶端的進程跟服務器的進程是一一對應的。
也就是說,在客戶端連接上服務器后,在客戶端與服務器端都會形成一個進程,客戶端上的我們叫做客戶端進程;而服務器上的我們叫做服務器進程。第二步:語句解析當客戶端把 SQL 語句傳送到服務器后,服務器進程會對該語句進行解析。
同理,這個解析的工作,也是在服務器端所進行的。雖然這只是一個解析的動作,但是,其會做很多“小動作”。
1. 查詢高速緩存(library cache)。服務器進程在接到客戶端傳送過來的 SQL 語句時,不會直接去數據庫查詢。
而是會先在數據庫的高速緩存中去查找,是否存在相同語句的執行計劃。如果在數據高速緩存中,則服務器進程就會直接執行這個 SQL 語句,省去后續的工作。
所以,采用高速數據緩存的話,可以提高 SQL 語句的查詢效率。一方面是從內存中讀取數據要比從硬盤中的數據文件中讀取數據效率要高,另一方面,也是因為這個語句解析的原因。
不過這里要注意一點,這個數據緩存跟有些客戶端軟件的數據緩存是兩碼事。有些客戶端軟件為了提高查詢效率,會在應用軟件的客戶端設置數據緩存。
由于這些數據緩存的存在,可以提高客戶端應用軟件的查詢效率。但是,若其他人在服務器進行了相關的修改,由于應用軟件數據緩存的存在,導致修改的數據不能及時反映到客戶端上。
從這也可以看出,應用軟件的數據緩存跟數據庫服務器的高速數據緩存不是一碼事。2. 語句合法性檢查(data dict cache)。
當在高速緩存中找不到對應的 SQL 語句時,則服務器進程就會開始檢查這條語句的合法性。這里主要是對 SQL 語句的語法進行檢查,看看其是否合乎語法規則。
如果服務器進程認為這條 SQL 語句不符合語法規則的時候,就會把這個錯誤信息,反饋給客戶端。在這個語法檢查的過程中,不會對 SQL 語句中所包含的表名、列名等等進行 SQL 他只是語法上的檢查。
3. 語言含義檢查(data dict cache)。若 SQL 語句符合語法上的定義的話,則服務器進程接下去會對語句中的字段、表等內容進行檢查。
看看這些字段、表是否在數據庫中。如果表名與列名不準確的話,則數據庫會就會反饋錯誤信息給客戶端。
所以,有時候我們寫 select 語句的時候,若語法與表名或者列名同時寫錯的話,則系統是先提示說語法錯誤,等到語法完全正確后,再提示說列名或表名錯誤。4. 獲得對象解析鎖(control structer)。
當語法、語義都正確后,系統就會對我們需要查詢的對象加鎖。這主要是為了保障數據的一致性,防止我們在查詢的過程中,其他用戶對這個對象的結構發生改變。
5. 數據訪問權限的核對(data dict cache)。當語法、語義通過檢查之后,客戶端還不一定能夠取得數據。
服務器進程還會檢查,你所連接的用戶是否有這個數據訪問的權限。若你連接上服務器的用戶不具有數據訪問權限的話,則客戶端就不能夠取得這些數據。
有時候我們查詢數據的時候,辛辛苦苦地把 SQL 語句寫好、編譯通過,但是,最后系統返回個 “沒有權限訪問數據”的錯誤信息,讓我們氣半死。這在前端應用軟件開發調試的過程中,可能會碰到。
所以,要注意這個問題,數據庫服務器進程先檢查語法與語義,然后才會檢查訪問權限。6. 確定最佳執行計劃 。
當語句與語法都沒有問題,權限也匹配的話,服務器進程還是不會直接對數據庫文件進行查詢。服務器進程會根據一定的規則,對這條語句進行優化。
不過要注意,這個優化是有限的。一般在應用軟件開發的過程中,需要對數據庫的 sql 語言進行優化,這個優化的作用要大大地大于服務器進程的自我優化。
所以,一般在應用軟件開發的時候,數據庫的優化是少不了的。當服務器進程的優化器確定這條查詢語句的最佳執行計劃后,就會將這條 SQL 語句與執行計劃保存到數據高速緩存(library cache)。
如此的話,等以后還有這個查詢時,就會省略以上的語法、語義與權限檢查的步驟,而直接執行 SQL 語句,提高 SQL 語句處理效率。第三步:語句執行語句解析只是對 SQL 語句的語法進行解析,以確保服務器能夠知道這條語句到底表達的是什么意思。
等到語句解析完成之后,數據庫服務器進程才會真正的執行這條 SQL 語句。這個語句執行也分兩種情況。
一是若被選擇行所在的數據塊已經被讀取到數據緩沖區的話,則服務器進程會直接把這個數據傳遞給客戶端,而不是從數據庫文件中去查詢數據。若數據不在緩沖區中,則服務器進程將從數據庫文件中查詢相關數據,并把這些數據放入到數據緩沖區中(buffer cache)。
第四步:提取數據當語句執行完成之后,查詢。
存儲過程與SQL語句是怎樣的
我的一位朋友說:他從臺灣知名技術作家李維先生的一本書中獲悉,如果用存儲過程封裝SQL語句,系統效率將有極大提升。
他做過實驗!!! --我相信朋友做過實驗,盡管非親眼所見。不過我估計他的實驗有問題,那樣的實驗不但蒙蔽了他,也蒙蔽了李維先生(如果他的著作中的內容沒有被誤會),甚至更多的人。
然而我必須拿出證據,方能使人信服。 后來遇到一個具體的問題:客戶端經常要向數據庫插入記錄。
在J2EE中,一個 Entity Bean Home 的 create 方法調用中,一般就沒用存儲過程。朋友立馬在觀點上持反對意見( 可能是因為他暫時有來得及否決J2EE ),認為要是J2EE能夠將“插入記錄”諸如此類動作改為對存儲過程的調用就好了。
我們因此再次發生爭論(我僅是反對朋友的看法,但也沒提出任何我自己的看法,因為要下一個結論是很不容易的)。最后我不得已而做了實驗,分別在 Oracle 10g 和 postgreSQL 8。
0。1 上。
實驗內容如下: A、建表腳本: create table ztest( fieldA integer primary key, fieldB varchar(128), fieldC varchar(128) ) B、客戶端請求 DBMS 執行的 insert SQL語句: insert into ztest values( ?1, ?2, ?3 ); -- ?1,?2,?3 將在運行時以合理的值替代之 C、客戶端調用的存儲過程(JDBC CallableStatement 調用): Oracle:(調用方式 call up_add(。 。
。),) create or replace procedure up_add( fieldA integer, fieldB varchar, fieldC varchar ) is begin insert into ztest values( fieldA, fieldB, fieldC); end; postgreSQL:(客戶端調用方式 select uf_add(。
。
) ) CREATE OR REPLACE FUNCTION uf_add (integer, varchar, varchar) RETURNS void AS' begin insert into ztest values($1,$2,$3); return; end; 'LANGUAGE 'plpgsql' VOLATILE RETURNS NULL ON NULL INPUT SECURITY INVOKER; D、環境: postgreSQL:數據庫服務器與客戶端程序“都在本機”并“同時運行” Oracle: 獨立數據庫服務器(測試時始終有人在慢慢打字,應該對機器性能無影響) 測試: 通過不同方式( 即 請求DBMS執行SQL語句 和 調用DBMS邏輯等價的存儲過程)向測試表中連續加入 1024 記錄 經多次反復測試,得結果如下 postgreSQL: 兩種方式下,測試時間均為 21- 24 seconds 之間 (每個結果的測試環境一致) Oracle: 8次 SQL 執行請求分別用時(ms) 5422 4750 3875 3812 5672 3531 3484 3547 6次 存儲過程調用分別用時(ms) 4578 4500 6297 4219 4547 5734 (每個結果的測試環境一致)由此可知,存儲過程封裝簡單的 SQL 語句,效率相當,且可能更低。 但很多朋友的確得出結論:存儲過程的確比SQL快。
為什么?---- 因為他們測試時寫了一個不具實際意義,同時也與SQL語句的“一次客戶端調用”不具可比性的測試用存儲過程。Oracle PL/SQL 描述方式如下,該方法一次調用就可以向數據表添加 1024 條記錄,連網絡通訊都省了。
怪不得性能有“千倍差異”! create or replace procedure up_add( ) is declare n:integer; begin n := 0; while( n 它與客戶端一次提交單條 SQL 語句沒有可比性:當一次只需要向DBMS提交一條新記錄,要這個存儲過程干什么呢?。
有關寫sql語句經驗的問題
看你用的是什么數據庫了,如果你用mysql 或者access這種小數據庫當然sql簡單點好,因為他們功能沒有那么強大,處理數據沒有那么塊,而且復雜的sql語句也不支持。
不過有點規模的公司數據庫都是用oracle的,功能十分強大,數據處理起來十分塊,現在的傾向是把盡量數據庫能處理的讓數據庫去處理,盡量不在程序上出來,把程序上的負擔轉移給數據庫。如果你用oracle數據庫還什么東西都用程序處理,只做簡單select insert delet update那么太浪費資源,大材小用了。
如果批量處理復雜數據的時候就會寫存儲過程了,簡單來說就是sql語句寫的程序。存儲過程使用越來越多也是這個道理。
sql存儲過程是什么
sql存儲過程說簡單點就是一個在t-sql下用戶可以自行定義的函數,
但是與一般的函數也有不同的地方,比如它的返回值只能RETURN(INT類型),如果你要輸出什么信息的話只能用OUTPUT.這也是存儲過程的一個特色吧,設定的參數可以有輸出。講起來有點抽象,給你個例子看看吧!
首先創建一個存儲過程
CREATE PROCEDURE cunchuguocheng
@a int,
@b int,
@c int output
as
begin
select @c = @a+@b
return(0)
end
然后調用這個存儲過程
declare @value int, --返回值
@c int --結果值
exec @value = cunchuguocheng 2,2,@c output
select @value as 返回值
select @c as 結果值
程序寫的很簡單,你運行一下我想你就會對存儲過程有所了解了。
求 存儲過程和Sql語句之間的區別 余額準確越好
1.存儲過程編譯器事先對存儲過程金星了語法檢查處理,避免了因SQL語句語法不正確引起運行時出現異常的問題.
2.只在保存存儲過程時數據庫服務器才進行編譯,以后每次執行存儲過程都不需要再進行重新編譯而一般的SQL語句每執行一次就需要數據庫引擎重新編譯一次,所以使用存儲過程可以提高數據庫執行效率(補充:這點很有用,特別是感覺你的程序和數據庫相關有點慢時可以用這點,幫你程序運行的更快)
3.可以在定義存儲過程的時候直接檢查運行的結果是否正確,可視化的設計界面提高了效率.
4.避免了查詢字符串中包含單引號等特殊字符可能會出現的問題
5.一個項目中可能會多處用到相同的SQL語句,使用存儲過程便于重用
6.修改靈活方便,當需要修改完成的功能時,只需要修改定義的存儲過程即可,不必單獨修改每一個引用.
對數據庫事務處理的方法
一 事務處理介紹 事務是這樣一種機制,它確保多個SQL語句被當作單個工作單 元來處理。
事務具有以下的作用: * 一致性:同時進行的查詢和更新彼此不會發生沖突,其他 用戶不會看到發生了變化但尚未提交的數據。 * 可恢復性:一旦系統故障,數據庫會自動地完全恢復未完 成的事務。
二 事務與一致性 事務是完整性的單位,一個事務的執行是把數據庫從一個一 致的狀態轉換成另一個一致的狀態。因此,如果事務孤立執行時 是正確的,但如果多個事務并發交錯地執行,就可能相互干擾, 造成數據庫狀態的不一致。
在多用戶環境中,數據庫必須避免同 時進行的查詢和更新發生沖突。這一點是很重要的,如果正在被 處理的數據能夠在該處理正在運行時被另一用戶的修改所改變, 那么該處理結果是不明確的。
不加控制的并發存取會產生以下幾種錯誤: 1 丟失修改(lost updates) 當多個事務并發修改一個數據時,不加控制會得出錯誤的結 果,一個修改會覆蓋掉另一個修改。 2 讀的不可重復性 當多個事務按某種時間順序存取若干數據時,如果對并發存 取不加控制,也會產生錯誤。
3 臟讀(DIRDY DATA),讀的不一致性 4 光標帶來的當前值的混亂 事務在執行過程中它在某個表上的當前查找位置是由光標表 示的。光標指向當前正處理的記錄。
當處理完該條記錄后,則指 向下一條記錄。在多個事務并發執行時,某一事務的修改可能產 生負作用,使與這些光標有關的事務出錯。
5 未釋放修改造成連鎖退出 一個事務在進行修改操作的過程中可能會發生故障,這時需 要將已做的修改回退(Rollback)。如果在已進行過或已發現錯 誤尚未復原之前允許其它事務讀已做過修改(臟讀),則會導致 連鎖退出。
6 一事務在對一表更新時,另外的事務卻修改或刪除此表的 定義。 數據庫會為每個事務自動地設置適當級別的鎖定。
對于前面 講述的問題:臟讀、未釋放修改造成的連鎖退出、一事務在對一 表更新時另外的事務卻修改或刪除此表的定義,數據庫都會自動 解決。而另外的三個問題則需要在編程過程中人為地定義事務或 加鎖來解決。
三 事務和恢復 數據庫本身肩負著管理事務的責任。事務是最小的邏輯工作 單元,在這個工作單元中,對數據庫的所有更新工作,要么必須 全部成功,要么必須全部失敗(回退)。
只要應用程序指定了某 段程序為一個事務并做了相應的處理(提交或回退),數據庫系 統會自動維護事務本身的特性。 四 ORACLE數據庫的事務定義 ORACLE事務從COMMIT、ROLLBACK、連接到數據庫或開始第一 條可執行的SQL語句時開始,到一條COMMIT、ROLLBACK語句或退出 數據庫時結束。
如果在一個事務中包含DDL語句,則在DDL語句的 前后都會隱含地執行COMMIT語句,從而開始或結束一個事務。 如果一個事務由于某些故障或者由于用戶改變主意而必須在 提交前取消它,則數據庫被恢復到這些語句和過程執行之前的狀 態。
利用ROLLBACK語句可以在COMMIT命令前隨時撤消或回退一個 事務。可以回退整個事務,也可以會退部分事務,但是不能回退 一個已經被提交的事務。
回退部分事務的ROLLBACK命令為: ROLLBACK to savepoint 存儲點名 存儲點是用戶放入事務中的標記,用來表示一個可被回退的 位置。存儲點通過在事務中放入一個SAVEPOINT命令而被插入。
該 命令的語法是: SAVEPOINT 存儲點名 如果在ROLLBACK語句中沒有給出存儲點名,則整個事務被回 退。 五 SYBASE數據庫的事務定義 SYBASE通過使用BEGIN TRANsaction和COMMIT TRANsaction命令指 示SQL將任意數目的語句作為一個單元來處理。
ROLLBACK TRANsaction 命令則允許用戶恢復到事務的開始,或恢復到事務內部已經被用SAVE TRANsaction命令定義的存儲點上。 BEGIN TRANsaction和COMMIT TRANsaction能夠包含任意數目的SQL 語句和存儲過程,方法很簡單: BEGIN TRANsaction [事務名稱] COMMIT TRANsaction 如果一個事務由于某些故障或者由于用戶改變主意而必須在提交 前取消它,則數據庫被恢復到這些語句和過程執行之前的狀態。
利用ROLLBACK TRANsaction命令可以在COMMIT TRANsaction命令 前隨時回退一個事務。可以回退整個事務,也可以回退部分事務,但 是不能回退一個已經被提交的事務。
ROLLBACK TRANsaction命令為: ROLLBACK TRANsaction [事務名|存儲點名] 存儲點名是用戶放入事務中的標記,用來表示一個可以被回退的 位置。存儲點名通過在事務中放入一個SAVE TRANsaction命令而被插 入。
該命令的句法是: SAVE TRANsaction 存儲點名 如果在ROLLBACK TRANsaction中沒有給出存儲點名或事務名,則 事務被回退到批處理中的第一個BEGIN TRANsaction語句處。
什么是存儲過程
存儲過程是事先經過編譯并存儲在數據庫中的一段SQL語句的集合,調用存儲過程可以簡化應用開發人員的很多工作,減少數據在數據庫和應用服務器之間的傳輸,對于提高數據處理的效率是有好處的。
優點:
1、重復使用:存儲過程可以重復使用,從而可以減少數據庫開發人員的工作量。
2、減少網絡流量:存儲過程位于服務器上,調用的時候只需要傳遞存儲過程的名稱以及參數就可以了,因此降低了網絡傳輸的數據量。
3、安全性:參數化的存儲過程可以防止SQL注入式攻擊,而且可以將Grant、Deny以及Revoke權限應用于存儲過程。
擴展資料:
存儲過程的缺點:
1、更改比較繁瑣:如果更改范圍大到需要對輸入存儲過程的參數進行更改,或者要更改由其返回的數據,則仍需要更新程序集中的代碼以添加參數、更新 GetValue() 調用,等等,這時候估計比較繁瑣。
2、可移植性差:由于存儲過程將應用程序綁定到 SQL Server,因此使用存儲過程封裝業務邏輯將限制應用程序的可移植性。如果應用程序的可移植性在您的環境中非常重要,則需要將業務邏輯封裝在不特定于 RDBMS 的中間層中。
參考資料來源:搜狗百科-存儲過程
轉載請注明出處華閱文章網 » sql語句處理的過程