A. 動態sql和靜態sql
這肯定是純隱嫌動態語攜物句啦~~get_counts()是個自定義函數做手,真要寫成靜態的就是
select count(*) from table_name
B. 靜態SQL和動態SQL的區別和測試實例
所謂SQL的動態和靜態,是指SQL語句在何時被編譯和執行,二者都是用在SQL嵌入式編程中的。
靜態SQL:在高級語言中,如果嵌入了SQL語句,而這個SQL語句的主體結構已經明確,例如在c的一段代碼中有一個待執行的SQL「select * from t1 where c1>5」,在編譯階段,就可以將這段SQL交給資料庫管理系統去分析,資料庫軟體可以對這段SQL進行語法解析,生成資料庫方面的可執行代碼,這樣的SQL稱為靜態SQL,即在編譯階段就可以確定資料庫要做什麼事情。
動態SQL:如果嵌入的SQL沒有明確給出,如在c中定義了一個字元數組類型的變數name:char name[32];,然後採用prepared Statement對象的execute方法去執行這個sql,該sql的值可能等於從文本框中讀取的一個SQL或者從鍵盤輸入的SQL,但具體是什麼,在編譯時無法確定,只有等到程序運行起來,在執行的過程中才能確定,這種SQL叫做動態SQL。例如每一種資料庫軟體都有能夠執行SQL語句的界面,那個界面接收的SQL就是動態SQL,因為資料庫廠商在做這個界面時,並不知道用戶會輸入哪些SQL,只有在該界面執行後,接收了用戶的實際輸入,才知道SQL是什麼。
注意:在SQL中如果某些參數沒有確定,如」select * from t1 where c1>? and c2#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE SQLDA;
/*此函數屬於靜態SQL編程*/
int DBSelect_static(){
EXEC SQL BEGIN DECLARE SECTION;
char _typename[32];
short _length;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT typename,length
INTO :_typename,:_length
FROM syscat.columns
WHERE tabname='SYSCOLUMNS' and colname='DEFAULT';
printf("【typename:%s】【length:%d】\n",_typename,_length);
}
/*此函數屬於靜態SQL編程:指定函數參數作為SQL語句的變數*/
int DBSelect_static_param(char *tbl_str,char *col_str){
EXEC SQL BEGIN DECLARE SECTION;
char _typename1[32];
short _length1;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT typename,length
INTO :_typename1,:_length1
FROM syscat.columns
WHERE tabname='tbl_str' and colname='col_str';
printf("【typename:%s】【length:%d】\n",_typename1,_length1);
}
/*此函數屬於動態SQL編程:SQL語句的結構是不確定的,需要根據用戶的輸入補全SQL語句*/
int DBUpdate_dynamic(){
EXEC SQL BEGIN DECLARE SECTION;
char _address1[32];
char _tablename[32];
char _tmp[32];
char buf[256];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT count(address1) INTO :_tmp FROM cisaddressinfo WHERE customid='100000100000000000178';
if(0==_tmp) {printf("Not Found!\n");return -1;}
memset(buf,0x00,sizeof(buf));
sprintf(buf,"update ");
printf("Pls input : tablename ->");
scanf("%s",&_tablename);
strcat(buf,_tablename);
strcat(buf," set address1=? where customid='100000100000000000178'");
EXEC SQL PREPARE project FROM :buf;
if(sqlca.sqlcode) perror("PREPARE");
printf("Pls input : address1 ->");
scanf("%s",&_address1);
EXEC SQL EXECUTE project USING :_address1;
if(sqlca.sqlcode) perror("EXECUTE");
EXEC SQL COMMIT WORK;
if(sqlca.sqlcode) perror("COMMIT");
}
/*此函數屬於動態SQL編程:使用sqlda數據結構組裝復雜多變的動態SQL*/
int DBSelect_dynamic(){
EXEC SQL BEGIN DECLARE SECTION;
char hostVarStmt[256];
EXEC SQL END DECLARE SECTION;
// 聲明兩個 SQLDA 指針,minsqlda 將是一個最小的 SQLDA 結構,用於 PREPARE 語句,
// 此時結果集的欄位數量未知,所以只需一個最小的 SQLDA,即包含 HEADER 和一個 SQLVAR
struct sqlda * minsqlda = (struct sqlda*)malloc(SQLDASIZE(1));
struct sqlda * fulsqlda = NULL;
strcpy(hostVarStmt, "select WUID from workprocess where muid = '185001'");
// PREPARE 將填寫 minsqlda 的 header,sqldabc 為 SQLDA 總長度,sqln 為 SQLVAR 數量,即欄位數量
EXEC SQL PREPARE STMT INTO :*minsqlda FROM :hostVarStmt;
// 根據從 minsqlda 中獲取的長度,分配完整的 SQLDA 結構 fulsqlda,其中將包括合適數量的 SQLVAR 結構
//結構sqlda的成員變數sqld返回select查詢語句的欄位的數目,可以根據此變數分配內存
fulsqlda = (struct sqlda *)malloc(SQLDASIZE(minsqlda->sqld));
// 使用 DESCRIBE 語句,獲取結果集中每個欄位的描述信息,包括各欄位的類型 (sqltype) 和長度 (sqllen)
EXEC SQL DESCRIBE STMT INTO :*fulsqlda;
int i;
for(i=0;i<minsqlda->sqld;i++)
{
// 根據每個欄位的長度,分配內存,將地址存儲在對應 SQLVAR 的 sqldata 中
// fulsqlda->sqlvar[i].sqldata=malloc(fulsqlda->sqlvar[i].sqllen);
fulsqlda->sqlvar[i].sqldata=malloc(32);
fulsqlda->sqlvar[i].sqlind=malloc(sizeof(short));
}
// 聲明游標
EXEC SQL DECLARE c1 CURSOR FOR STMT;
EXEC SQL OPEN c1;
EXEC SQL WHENEVER not found goto no_more_data;
// 讀取記錄,記錄中每個欄位的內容將寫入 fulsqlda 中對應 SQLVAR 結構的 sqldata 指向的內存
// EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
// 循環讀取所有記錄
for (;;)
{
EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
for(i=0;i<minsqlda->sqld;i++){
printf("%d %s\n",fulsqlda->sqlvar[i].sqltype,fulsqlda->sqlvar[i].sqldata);
usleep(10000);
}
}
return 0;
no_more_data:
printf("\nEND of Data\n");
free(minsqlda);
free(fulsqlda);
EXEC SQL CLOSE c1;
return 0;
}
int main(){
/*連接資料庫*/
EXEC SQL CONNECT TO ezeelink USER ezeelink USING EA704075ezeelink;
DBSelect_static();
DBSelect_static_param("SYSCOLUMNS","DEFAULT");
DBUpdate_dynamic();
DBSelect_dynamic();
no_more_data:
;
return 0;
}
案例輸出結果如下:
【typename:VARCHAR】【length:254】
【typename:VARCHAR】【length:254】
Pls input : tablename ->cisaddressinfo
Pls input : address1 ->ShangHai
452 cis505
452 cis506
452 pub806
452 ips007
452 ips032
452 dps302
END of Data
注意:
如果使用動態SQL編程編寫select查詢語句並保存結果,需要使用sqlda數據結構的,同時使用SQL的特性和功能,如:PREPARE ,EXECUTE ,DESCRIBE , DECLARE CURSE C1 FOR … , OPEN CURSE , CLOSE CURSE ….等等
建議:
動態SQL適用於表名及查詢欄位名未知的情況。在已知查詢欄位名及表名的情況下,使用動態SQL(字元串拼接方式)會增加硬解析的開銷,在這種情況下,建議使用靜態SQL,這樣可以提高執行效率。在過程過程用拼湊的動態sql效率並不高,有時候還不如程序直接傳遞sql.靜態SQL是前置編譯綁定,動態SQL是後期執行時才編譯綁定
C. DELPHI基礎教程:SQL編程(一)[2]
靜態方式是把SQL命令文作為TQuery部件的SQL屬性值進行設置 這樣 當執行應用程序時 Delphi便執行TQuery部件SQL屬性中設置的SQL命令 如果是SQL中的查詢命令 把TQuery部件通過TDataSource部件與數據控制部件相連 查詢的結果將會顯示在與 TQuery部件相連接的數據瀏覽部件中 動態SQL語句是指SQL語句中包含一些參數變數 在程序中可以為這些參數賦值 在程序運行過程中 各個參數值是變化的 TQuery部件的SQL 屬性中的SQL語句的編寫也有兩種方法 一種方法是在程序設置階段便將相應的SQL語句寫入到TQuery的SQL屬性中 另一種方法是在Delphi開發的應用程序將SQL語差敏句 包含在Pascal代碼單元中
在SQL編程中使用TQuery部件的具體方法步驟如下
①為TQuery部件設置DatabaseName屬性 它可以是用BDE建立的資料庫的別名 或桌面資料庫系統中的目錄名或資料庫伺服器中的文件名 如果在應用中使用了TDatabase 部件 那麼TQuery部件的DatabaseName屬性可以是TDatabase部件中定義的一個資料庫別名 詳細情況請參看 TDatabase部件的使用 ;
②為TQuery部件設置SQL屬性 TQuery部件的SQL屬性值就是應用程序要執行的SQL 命令文本 設置SQL屬性有兩種方法
● 在程序設計過程中 我們可以通過對象瀏覽器(Object Inspector)編輯SQL屬性在Object Inspector中選擇SQL屬性 這樣會打開String List Editor窗口 在其中我們便可以編寫SQL命令 我還可以打開Visual Query Builder來編寫SQL命令 (只有Delphi的客戶/伺服器版本才具有這一工具)
● 將SQL命令包含在Pascal代碼單元中
旦則在程序運行過程中 首先調用TQuery部件的Close方法關閉當前的TQuery部件 然後調用Clear方法清除SQL屬性 並說明新的SQL命令文本 然後調用Add方法 將新的SQL命令文本加入到SQL屬性中
③通過調用TQuery部件的Open方法或ExecSQl方法執行 SQL 命令 Open 方法只執行Select命令 ExecSQL方法還可以執行其它的SQL命令 Open方法和ExecSQL 方法的區別我們在後面的章節里會進一步地加以討論的
如果使用動態SQL語句 首先調用prepare方法 給動態SQL語句中的參數賦值 然後再調用Open方法或ExecSQL方法 調用propare 方法並不是必須的 但是對於要多次執行TQuery部件中SQL屬性中的動態SQL語句 調用Prepare可以大大提高TQuery部件執行SQL語句的性能
在TQuery部虛遲枝件中編寫簡單的SQL查詢命令
在這一節里我們將學習如何使用TQuery部件編寫簡單的SQL查詢命令 並在Delphi 應用程序中實現SQL查詢
例如 如果我們想查詢出表Customer DB中客戶的編號和公司名稱 我們按下列步驟來實現
①在應用窗體中放置一個TQuery部件 一個TDataSource部件一個TDataGrid部件 並將它們連接起來
②設置窗體TQuery 部件Query 的DatabaseName屬性值為DBDEMOS
③雙擊Object Inspector窗口中Query 的SQL 屬性 Delphi 將顯示 String List Editor窗口
④在圖 中的窗口中輸入SQL語句
Select CustNo Company From Custormer;
⑤單擊OK按鈕 關閉String List Editor窗口
⑥設置Query的Open屬性為True
SQL語言編程概述
在Delphi應用程序中的SQL命令語句是包含在TQuery部件的SQL屬性中 TQuery部件的SQL屬性是TString類型的 也就是說SQL屬性值是一個字元串列表 這個字元串列表非常類似於一個字元串類型的數組 有關TString類型的信息請參看聯機幫助 在前一節里我們介紹了TQuery部件可以執行兩種SQL語句
● 靜態SQL語句
● 動態SQL語句
靜態SQL語句在程序設計時便已固定下來 它不包含任何參數和變數 例如下面的語句便是一條靜態SQL語句
Select * From Cusromer Where CustNo = ;
而動態SQL語句 也被稱作參數化的語句 在其中間包含著表示欄位名或表名的參數 例如下面的語句是一條動態SQL語句
Select * From Customer Where CustNo =: Number;
其中的變數Number便是一個參數變數 它由一個冒號引導 在程序運行過程中 必須要為該參數賦值 該條SQL語句才能正確執行 每次運行應用程序時可以為該參數變數賦予不同的值
SQL命令文本的編寫
使用String List Editor編寫
我們要為TQuery部件的SQL屬性設置SQL命令文本時 可以在應用窗體中選擇TQuery部件且雙擊Object Inspector窗口中的SQL屬性 這樣便打開了String List Editor 窗口 在該窗口中我們便可以編寫各種SQL命令 如圖 所示
在編寫完適當的SQL語句之後 選擇 OK 按鈕便可以將編輯器中的 SQL 命令文裝入到TQuery部件的SQL屬性中 選擇SAVE按鈕可以將編寫好的SQL命令保存到一個文件中供以後編程時使用 我們在編寫SQL命令文本時還可以選擇Load按鈕從一個 SQL 命令文件中調入SQL命令 在程序運行過程中 要想設置TQuery部件的SQL屬性 必須首先調用Close方法 關閉TQuery部件 然後再調用Clear方法清除SQL屬性中現存的SQL命令語句 最後再調用Add方法為SQL屬性設置新的SQL命令語句 例如
Query Close {關閉Query )
Query SQL Clear {清除SQL屬性中的SQL命令語句}
Query SQL Add( Select * From Country )
Query SQL Add( Where Name = ARGENTINA )
在為TQuery部件設置SQL屬性時調用Close方法總是很安全的 如果TQuery部件已經被關閉了 調用Close方法時不會產生任何影響 在應用程序中為SQL屬性設置新的SQL 命令語句時 必須要調用Clear方法以清除SQL屬性中現存的SQL命令語句 如果不調用Clear方法 便調用Add方法向SQL屬性中設置SQL命令語句 那麼新設置的SQL命令語句會追加在現存SQL命令語句後面 在程序運行時常常會出現出乎意料的查詢結果甚至程序無法運行下去
在這里要特別注意的 一般情況下TQuery部件的SQL屬性只能包含一條完整的SQL語句 它不允許被設置成多條SQL語句 當然有些資料庫伺服器也支持在TQuery部件的SQL屬性中設置多條SQL語句 只要資料庫伺服器允許這樣 我們在編程時可以為 SQL 屬性設置多條SQL語句
lishixin/Article/program/Delphi/201311/25145
D. PL/SQL開發中動態SQL的使用方法
內容摘要 在PL/SQL開發過程中 使用SQL PL/SQL可禪仔以實現大部份的需求 但是在某些特殊的情況下 在PL/SQL中使用標準的SQL語句或DML語句不能實現自己的需求 比如需要動態建表或某個不確定的操作需要動態正宏執行 這就需要使用動態SQL來實現 本文通過幾個實例來詳細的講解動態SQL的使用 本文適宜讀者范圍 Oracle初級 中級 系統環境 OS windows Professional (英文版)Oracle 正文 一般的PL/SQL程序設計中 在DML和事務控制的語句中可以直接使用SQL 但是DDL語句及系統控制語句卻不能在PL/SQL中直接使用 要想實現在PL/SQL中使用DDL語句及系統控制語句 可以通過使用動態SQL來實現 首先我們應該了解舉襲冊什麼是動態SQL 在Oracle資料庫開發PL/SQL塊中我們使用的SQL分為 靜態SQL語句和動態SQL語句 所謂靜態SQL指在PL/SQL塊中使用的SQL語句在編譯時是明確的 執行的是確定對象 而動態SQL是指在PL/SQL塊編譯時SQL語句是不確定的 如根據用戶輸入的參數的不同而執行不同的操作 編譯程序對動態語句部分不進行處理 只是在程序運行時動態地創建語句 對語句進行語法分析並執行該語句 Oracle中動態SQL可以通過本地動態SQL來執行 也可以通過DBMS_SQL包來執行 下面就這兩種情況分別進行說明 一 本地動態SQL 本地動態SQL是使用EXECUTE IMMEDIATE語句來實現的 本地動態SQL執行DDL語句 需求 根據用戶輸入的表名及欄位名等參數動態建表 create or replace procere proc_test(table_name in varchar 表名field in varchar 欄位名datatype in varchar 欄位類型field in varchar 欄位名datatype in varchar 欄位類型) asstr_sql varchar ( );beginstr_sql:= create table ||table_name|| ( ||field || ||datatype || ||field || ||datatype || ) ;execute immediate str_sql; 動態執行DDL語句exceptionwhen others thennull;end ;以上是編譯通過的存儲過程代碼 下面執行存儲過程動態建表 SQL> execute proc_test( dinya_test id number( ) not null name varchar ( ) );PL/SQL procere successfully pletedSQL> desc dinya_test;Name TypeNullable Default Comments ID NUMBER( )NAME VARCHAR ( ) YSQL>到這里 就實現了我們的需求 使用本地動態SQL根據用戶輸入的表名及欄位名 欄位類型等參數來實現動態執行DDL語句 本地動態SQL執行DML語句 需求 將用戶輸入的值插入到上例中建好的dinya_test表中 create or replace procere proc_insert(id in number 輸入序號name in varchar 輸入姓名) asstr_sql varchar ( );beginstr_sql:= insert into dinya_test values(: : ) ;execute immediate str_sql using id name; 動態執行插入操作exceptionwhen others thennull;end ;執行存儲過程 插入數據到測試表中 SQL> execute proc_insert( dinya );PL/SQL procere successfully pletedSQL> select * from dinya_test;IDNAME dinya在上例中 本地動態SQL執行DML語句時使用了using子句 按順序將輸入的值綁定到變數 如果需要輸出參數 可以在執行動態SQL的時候 使用RETURNING INTO 子句 如 declarep_id number:= ;v_count number;beginv_string:= select count(*) from table_name a where a id=:id ;execute immediate v_string into v_count using p_id;end ;更多的關於動態SQL中關於返回值及為輸出輸入綁定變數執行參數模式的問題 請讀者自行做測試 二 使用DBMS_SQL包 使用DBMS_SQL包實現動態SQL的步驟如下 A 先將要執行的SQL語句或一個語句塊放到一個字元串變數中 B 使用DBMS_SQL包的parse過程來分析該字元串 C 使用DBMS_SQL包的bind_variable過程來綁定變數 D 使用DBMS_SQL包的execute函數來執行語句 使用DBMS_SQL包執行DDL語句 需求 使用DBMS_SQL包根據用戶輸入的表名 欄位名及欄位類型建表 create or replace procere proc_dbms_sql(table_name in varchar 表名field_name in varchar 欄位名datatype in varchar 欄位類型field_name in varchar 欄位名datatype in varchar 欄位類型)asv_cursor number; 定義游標v_string varchar ( ); 定義字元串變數v_row number; 行數beginv_cursor:=dbms_sql open_cursor; 為處理打開游標v_string:= create table ||table_name|| ( ||field_name || ||datatype || ||field_name || ||datatype || ) ;dbms_sql parse(v_cursor v_string dbms_sql native); 分析語句v_row:=dbms_sql execute(v_cursor); 執行語句dbms_sql close_cursor(v_cursor); 關閉游標exceptionwhen others thendbms_sql close_cursor(v_cursor); 關閉游標raise;end;以上過程編譯通過後 執行過程創建表結構 SQL> execute proc_dbms_sql( dinya_test id number( ) not null name varchar ( ) );PL/SQL procere successfully pletedSQL> desc dinya_test ;Name TypeNullable Default Comments ID NUMBER( )NAME VARCHAR ( ) YSQL> 使用DBMS_SQL包執行DML語句 需求 使用DBMS_SQL包根據用戶輸入的值更新表中相對應的記錄 查看錶中已有記錄 SQL> select * from dinya_test ;ID NAME Oracle CSDN ERPSQL>建存儲過程 並編譯通過 create or replace procere proc_dbms_sql_update(id number name varchar )asv_cursor number; 定義游標v_string varchar ( ); 字元串變數v_row number; 行數beginv_cursor:=dbms_sql open_cursor; 為處理打開游標v_string:= update dinya_test a set a name=:p_name where a id=:p_id ;dbms_sql parse(v_cursor v_string dbms_sql native); 分析語句dbms_sql bind_variable(v_cursor :p_name name); 綁定變數dbms_sql bind_variable(v_cursor :p_id id); 綁定變數v_row:=dbms_sql execute(v_cursor); 執行動態SQLdbms_sql close_cursor(v_cursor); 關閉游標exceptionwhen others thendbms_sql close_cursor(v_cursor); 關閉游標raise;end;執行過程 根據用戶輸入的參數更新表中的數據 SQL> execute proc_dbms_sql_update( csdn_dinya );PL/SQL procere successfully pletedSQL> select * from dinya_test ;ID NAME Oracle csdn_dinya ERPSQL>執行過程後將第二條的name欄位的數據更新為新值csdn_dinya 這樣就完成了使用dbms_sql包來執行DML語句的功能 使用DBMS_SQL中 如果要執行的動態語句不是查詢語句 使用DBMS_SQL Execute或DBMS_SQL Variable_Value來執行 如果要執行動態語句是查詢語句 則要使用DBMS_SQL define_column定義輸出變數 然後使用DBMS_SQL Execute DBMS_SQL Fetch_Rows DBMS_SQL Column_Value及DBMS_SQL Variable_Value來執行查詢並得到結果 總結說明 在Oracle開發過程中 我們可以使用動態SQL來執行DDL語句 DML語句 事務控制語句及系統控制語句 但是需要注意的是 PL/SQL塊中使用動態SQL執行DDL語句的時候與別的不同 在DDL中使用綁定變數是非法的(bind_variable(v_cursor :p_name name)) 分析後不需要執行DBMS_SQL Bind_Variable 直接將輸入的變數加到字元串中即可 另外 DDL是在調用DBMS_SQL lishixin/Article/program/SQLServer/201311/22089
E. 如果執行時 發現sql是一個字元串變數 那這樣的sql屬於動態sql 這句話什麼意思
SQL語句有2種,一種是靜態的,一種是動態的返和老
靜態棚睜SQL是寫好的,動態SQL自己可以拼接的,也可以帶佔位漏升符的
這樣明白了嗎?
F. 靜態sql 動態sql
按理說,在開發語言里拼好SQL語句後,調用資料庫聯接執行的,都是靜態SQL語句。因為對於資料庫來說,提供的是一個固定的SQL。
動態SQL語句,是指在資料庫對SQL進行編譯的時候,資料庫的表或是欄位名都是未定的,只是一個字元串,最後資料庫是使用函數execute 來執行字元串的,這叫動態SQL。
比如 select column_name from table_name 這個是靜態SQL。
execute (' select column_name from table_name' ) 這個是動態SQL,可以在運行前把括弧里的串任意組合。
G. 動態sql和靜態sql到底是說明區別
靜態sql:語句類型在編程時候必須是確定好的。比如
createprocdbo.Usp_Test
(@IDint)
as
begin
select*fromemployeewhereID=@ID
end
GO
以上只有@ID是變數,其他的都必須是固定語句。
動態sql:語句類型可以在運行期間指定,比如
createprocdbo.Usp_Test
(@IDint)
as
begin
declare@strsqlnvarchar(8000)
set@strsql=N'select*fromemployeewhereID='+cast(@IDasnvarchar(20))
exec@strsql
end
GO
靜態sql的好處就是事先SQL已經預編譯,執行計劃已生成,執行起來效率要高
而動態sql是在運行時動態生成執行計劃的。
兩者沒有哪種最好,哪種最優,都是根據業務,具體判斷應該使用何種方式來實現
H. 存儲過程含有動態SQL,與靜態SQL有什麼差別
靜態sql是所有的內容都是固定且確定的的sql,比如select * from emp where empno=1;
所謂動態sql主要有兩種,其中一個是含有參數的sql。比如select * from emp where empno="一個變數或者輸入值",也就是說這個參數是一個變數,不是一個固定的量,也就是動態sql。
還有一種動態sql是拼裝語句的動態sql,也就是語句是拼裝起來的。這種多出現在存儲過程中。比如頁面有一個輸入的頁面,有八個空,有三個空必填,其他空可填可不填,那麼這個就是一個拼接的語句,最簡單的就是其他欄位一律null,也可以根據輸入的地方判斷語句的具體內容,這就是拼接的語句。