c動態sql
有時需要在oracle
存儲過程中執行動態sql
語句
,例如表名是動態的,或欄位是動態的,或查詢命令是動態的,可用下面的方法:
set
serveroutput
on
declare
n
number;
sql_stmt
varchar2(50);
t
varchar2(20);
begin
execute
immediate
'alter
session
set
nls_date_format=''yyyymmdd''';
t
:=
't_'
||
sysdate;
sql_stmt
:=
'select
count(*)
from
'
||
t;
execute
immediate
sql_stmt
into
n;
dbms_output.put_line('the
number
of
rows
of
'
||
t
||
'
is
'
||
n);
end;
如果動態sql
語句
很長很復雜,則可用包裝.
create
or
replace
package
test_pkg
is
type
cur_typ
is
ref
cursor;
procere
test_proc
(v_table
varchar2,t_cur
out
cur_typ);
end;
/
create
or
replace
package
body
test_pkg
is
procere
test_proc
(v_table
varchar2,t_cur
out
cur_typ)
is
sqlstr
varchar2(2000);
begin
sqlstr
:=
'select
*
from
'||v_table;
open
t_cur
for
sqlstr;
end;
end;
/
在oracle
中批量導入,導出和刪除表名以某些字元開頭的表
spool
c:\a.sql
select
'drop
table
'
||
tname
||
';'
from
tab
where
tname
like
't%';
spool
off
@c:\a
㈡ ProC動態SQL EXEC SQL PREPARE sql FROM :c_sql;
(1)動態SQL1:
不能是查詢(SELECT)語句,並且沒有宿主變數.
用法:拼一句動態SQL語句,並用EXECUTE
IMMEDIATE執行,如:
EXEC
SQL
EXECUTE
IMMEDIATE
CREATE
TABLE
test
(test_col
VARCHAR2(4));
EXEC
SQL
EXECUTE
IMMEDIATE
INSERT
INTO
TABLE
test
('AAAA');
EXEC
SQL
EXECUTE
IMMEDIATE
DELETE
test
WHERE
test_col='AAAA';
(2)動態SQL2:
不能是查詢(SELECT)語句,並且輸入的宿主變數數目是知道的,
用法:拼一句動態SQL語句,用PREPARE,EXECUTE語句執行.
strcpy(sqlstring,
"DELETE
FROM
test
WHERE
test_col
=
:?");
EXEC
SQL
PREPARE
sqlproc
FROM
:sqlstring;
EXEC
SQL
EXECUTE
sqlproc
USING
:emp_number;
㈢ 靜態的SQL 和動態的SQL有什麼區別
靜態 SQL:靜態 SQL 語句一般用於嵌入式 SQL 應用中,在程序運行前,SQL 語句必須是確定的,例如 SQL 語句中涉及的列名和表名必須是存在的。靜態 SQL 語句的編譯是在應用程序運行前進行的,編譯的結果會存儲在資料庫內部。而後程序運行時,資料庫將直接執行編譯好的 SQL 語句,降低運行時的開銷。
動態 SQL:動態 SQL 語句是在應用程序運行時被編譯和執行的,例如,使用 DB2 的互動式工具 CLP 訪問資料庫時,用戶輸入的 SQL 語句是不確定的,因此 SQL 語句只能被動態地編譯。動態 SQL 的應用較多,常見的 CLI 和 JDBC 應用程序都使用動態 SQL。
㈣ proc*c中怎麼使用動態sql語句
proc*c中怎麼使用動態sql語句
MSSQL為我們提供了兩種動態執行SQL語句的命令,分別是EXEC和sp_executesql;通常,sp_executesql則更具有優勢,它提供了輸入輸出介面,而EXEC沒有。
㈤ pro *c是什麼還有動態sql是什麼
sql server
proc創建儲存過程時的關鍵字
create proc 存儲過程名
as
……
動態sql
可以理解為拼接的sql語句
如:
declare @sql varchar(max)
declare @id int
set @id = 123
set @sql = 'select * from aaa where id = ' + @id
exec(@sql)
這樣的,根據不同情況拼接成不同的sql語句以及條件,這就是動態,可變的
㈥ C語言環境下如何使用動態SQL
你真是牛人呀。資料庫類型那麼多,有oraclemysqlDB2SQLSQLsevera。你使用的那種。
相對於來說我使用oracle多。
給你一個pro*c的操作實例吧
/ 定義符號常數
#define USERNAME "SCOTT"
#define PASSWORD "x"
#include <stdio.h>
// 說明SQLCA和ORACA
EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE ORACA;
// 啟用ORACLE通訊區:ORACA=YES,使它能被使用
EXEC ORACLE OPTION (ORACA=YES);
// 說明SQL變數
EXEC SQL BEGIN DECLARE SECTION;
char* username=USERNAME;
char* password=PASSWORD;
VARCHAR sqlstmt[80];
int emp_number;
VARCHAR emp_name[15];
VARCHAR job[50],job1[50],job2[50];
float salary;
EXEC SQL END DECLARE SECTION;
main()
{
EXEC SQL WHENEVER SQLERROR GOTO sqlerror;
// 發生錯誤時,保存SQL語句至ORACA
oraca.orastxtf=ORASTFERR;
// 登錄到ORACLE
EXEC SQL CONNECT :username IDENTIFIED BY :password;
printf("/nConnect to ORACLE./n");
// 構造動態SQL語句
sqlstmt.len=sprintf(sqlstmt.arr,"INSERT INTO EMP(EMPNO,ENAME,JOB,SAL)VALUES(:V1,:V2,:V3,:V4)");
// 顯示SQL語句
puts(sqlstmt.arr);
// 用PREPARE語句分析當前的動態INSERT語句,語句名是S
EXEC SQL PREPARE S FROM :sqlstmt;
// 循環插表
for(;;)
{
printf("/nEnter employee number:");
scanf("%d",&emp_number);
if(emp_number==0)break;
printf("/nEnter employee name:");
scanf("%s",&emp_name.arr);
emp_name.len=strlen(emp_name.arr);
printf("/nEnter employee job:");
scanf("%s",&job.arr);
job.len=strlen(job.arr);
salary = 0; // With VC6, Missing this line will cause C Run-Time Error R6002.
printf("/nEnter salary:");
scanf("%f",&salary);
EXEC SQL EXECUTE S USING :emp_number,:emp_name,:job,:salary;
}
// 提交事務,退出ORACLE
EXEC SQL COMMIT RELEASE;
printf("/nHave a good day!/n");
exit(0);
sqlerror:
// 列印錯誤信息
printf("/n%.*s/n",sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc);
// 列印出錯SQL語句
printf("/n/"%.*s.../"/n",oraca.orastxt.orastxtl,oraca.orastxt.orastxtc);
// 列印出錯SQL語句所在行號及所在文件名
printf("on line %d of %.*s/n/n",oraca.oraslnr,
oraca.orasfnm.orasfnml,oraca.orasfnm.orasfnmc);
// 回滾事務,退出ORACLE
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK RELEASE;
exit(1);
}
㈦ 靜態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#中使用動態sql問題 新手 急!!!!!!!!!!滿意加50分!!!!!!
用什麼動態sql啊,這種情況下,把用戶輸入的的欄位寫在C#的sql語句中就好了,又不是要你在sql中來實現動態欄位查詢。
所謂的動態sql,說簡單點就是在sql查詢中,以字元串的方式組合查詢sql語句,最後使用exec關鍵字來執行這個組合的查詢字元串:
declare @sql varchar(500)
set @sql='select top 1 from master.sys.objects'
exec (@sql)
就是一段簡單的動態sql
㈨ 動態SQL中的重復佔位符如何與綁定變數進行
BEGIN calc_stats(:x, :x, :y, :x); END 是一個PL/SQL 代碼段,而非 insert into t6 (a,b,c) values (:x,:y,:x) 這樣的DML,標准SQL語句。
在EXECUTE IMMEDIATE 中,利用USING語句綁定變數時,Oracle遵循針對PL/SQL存儲過程使用佔位符名稱匹配的原則,而針對SQL語句則採用佔位符位置匹配的原則。
PL/SQL 用戶指南與參考 中的 例子如下:
動態SQL語句中的佔位符與USING子句中的綁定參數是位置關聯的,而不是名稱關聯。所以,如果在SQL語句中同樣的佔位符出現兩次或多次,那麼,它的每次出現都必須與一個USING子句中的綁定參數相關聯。例如下面的動態字元串:
sql_stmt := 'INSERT INTO payroll VALUES (:x, :x, :y, :x)';
我們可以為動態字元串編寫對應的USING子句:
EXECUTE IMMEDIATE sql_stmt USING a, a, b, a;
但 是,動態PL/SQL塊中只有唯一的佔位符才與USING子句中的綁定參數按位置對應。所以,如果一個佔位符在PL/SQL塊中出現兩次或多次,那麼所有 這樣相同的佔位符都只與USING語句中的一個綁定參數相對應。比如下面的例子,第一個佔位符(x)與第一個綁定參數(a)關聯,第二個佔位符(y)與第 二個綁定參數(b)關聯。
DECLARE
a NUMBER := 4;
b NUMBER := 7;
BEGIN
plsql_block := 'BEGIN calc_stats(:x, :x, :y, :x); END';
EXECUTE IMMEDIATE plsql_block
USING a, b;
...
END;
---------------------------------------------------------------------------------------------
CREATE TABLE T1 (N1 NUMBER, N2 NUMBER,N3 NUMBER,N4 NUMBER);
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO T1(N1,N2,N3,N4) VALUES (:N1,:N2,:N2,:N1)' USING 1,2;
END;
/
*
ERROR at line 1:
ORA-01008: not all variables bound
ORA-06512: at line 2
BEGIN
EXECUTE IMMEDIATE 'BEGIN INSERT INTO T1(N1,N2,N3,N4) VALUES (:N1,:N2,:N2,:N1); END;' USING 1,2;
END;
/
PL/SQL procere successfully completed.
SELECT * FROM T1;
N1 N2 N3 N4
---------- ---------- ---------- ----------
1 2 2 1
----------------------------------------------