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,也可以根据输入的地方判断语句的具体内容,这就是拼接的语句。