SQLServer(綁定變量的分析理解)

字號(hào):

綁定變量
    在查詢(xún)中,綁定變量是一個(gè)占位符。例如,為了檢索員工123的記錄,可以查詢(xún):
    select * from scott.emp where empno = 123;
    另外,也可以查詢(xún):
    select * from scott.emp where empno = :empno;
    在典型系統(tǒng)中,查詢(xún)員工123一次,可能再也不會(huì)查詢(xún)。以后,將查詢(xún)員工456,然后查詢(xún)員工789等等。
    如果在查詢(xún)中使用文字(常量),那每次每個(gè)查詢(xún)都是一個(gè)新查詢(xún),即在數(shù)據(jù)庫(kù)中以前沒(méi)有過(guò)的查詢(xún)。每次查詢(xún)必需經(jīng)過(guò)分析、限定(名稱(chēng)解析)、
    安全檢查、優(yōu)化等等,簡(jiǎn)單的說(shuō),執(zhí)行的每條語(yǔ)句在每次執(zhí)行時(shí)都將必需經(jīng)過(guò)編譯。
    第二個(gè)查詢(xún)使用了綁定變量:empno,它的值在查詢(xún)執(zhí)行時(shí)提供。查詢(xún)經(jīng)過(guò)一次編譯后,考試大提示查詢(xún)方案存儲(chǔ)在共享池(庫(kù)高速緩存)中,可以用來(lái)檢索和重用。
    在性能的差異是巨大的。
    ---
    如果使用綁定變量,提交引用相同對(duì)象的完全相同的查詢(xún)的人將使用共享池中的編譯方案。只需編譯子例程一次,就可以重復(fù)使用。
    不僅使用較少的資源,而且可以減少鎖存時(shí)間,降低鎖存頻率。這會(huì)他提高性能,并大大地提高可伸縮性。
    --測(cè)試(根據(jù)機(jī)器不同而不同哦,本測(cè)試同一機(jī)器)
    --使用了綁定變量的
    declare
    type rc is ref cursor;
    l_rc rc;
    l_dummy all_objects.object_name%type;
    l_start number default sys.dbms_utility.get_time;
    begin
    for i in 1..1000 loop
    open l_rc for
    'select a.object_name from all_objects a where a.object_id = :X' using i;
    fetch l_rc into l_dummy;
    close l_rc;
    end loop;
    dbms_output.put_line(round((sys.dbms_utility.get_time - l_start)/100,2)||'秒');
    end;
    -------------------------------
    --結(jié)果輸出為0.91秒
    -------------------------------
    --沒(méi)有綁定
    declare
    type rc is ref cursor;
    l_rc rc;
    l_dummy all_objects.object_name%type;
    l_start number default sys.dbms_utility.get_time;
    begin
    for i in 1..1000 loop
    open l_rc for
    'select a.object_name from all_objects a where a.object_id = ' ||i;
    fetch l_rc into l_dummy;
    close l_rc;
    end loop;
    dbms_output.put_line(round((sys.dbms_utility.get_time - l_start)/100,2)||'秒');
    end;
    -------------------------------
    --結(jié)果輸出為22.42秒
    -------------------------------
    查詢(xún)通常只是因?yàn)楦淖僿here子句中的內(nèi)容而產(chǎn)生不同的結(jié)果。為了在這種情況下避免硬解析,需要使用綁定變量(bind variable)。它是用戶(hù)放入查詢(xún)中的占位符,它會(huì)告訴Oracle"我會(huì)隨后為這個(gè)變量提供一個(gè)值,現(xiàn)在需要生成一個(gè)方案,但我實(shí)際執(zhí)行語(yǔ)句的時(shí)候,我會(huì)為您提供應(yīng)該使用的實(shí)際值"。
    select * from emp where ename='KING'; //不使用綁定變量
    select * from emp where ename=:bv //使用綁定變量
    一般在 procedure or function 中使用,可以?xún)?yōu)化共享池的使用。
    例子:
    SQL> set serveroutput on
    SQL> drop table hxz_12 ;
    表已丟棄。
    SQL> create table hxz_12(c number);
    表已創(chuàng)建。
    SQL> --考試大提示未綁定變量
    SQL> declare
    2 l_start number default dbms_utility.get_time;
    3 l_tabname varchar2(10) default 'hxz_12';
    4 begin
    5 for x in 1 .. 10000 loop
    6 Execute immediate 'insert into '||l_tabname||'(c) values (' || x || ')';
    7 end loop;
    8 dbms_output.put_line(round((dbms_utility.get_time - l_start) / 100, 2) ||
    9 ' seconds...');
    10 commit;
    11 end;
    12 /
    2.89 seconds...
    PL/SQL 過(guò)程已成功完成。
    SQL> declare
    2 l_start number default dbms_utility.get_time;
    3 l_tabname varchar2(10) default 'hxz_12';
    4 begin
    5 for x in 1 .. 10000 loop
    6 Execute immediate 'insert into '||l_tabname||'(c) values (:v)'
    7 using x;
    8 end loop;
    9 dbms_output.put_line(round((dbms_utility.get_time - l_start) / 100, 2) ||
    10 ' seconds...');
    11 commit;
    12 end;
    13 /
    .74 seconds...
    PL/SQL 過(guò)程已成功完成。
    SQL>
    Examda提示可見(jiàn)進(jìn)行了變量綁定執(zhí)行起來(lái)效果比沒(méi)有進(jìn)行變量綁定的要好很多。