当前位置:首页 » 编程语言 » dal层动态sql语句
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

dal层动态sql语句

发布时间: 2022-07-10 21:41:45

‘壹’ 如何动态执行sql语句

这里只介绍动态SQL的使用。关于动态SQL语句的语法,参见:http://blog.csdn.NET/chiclewu/article/details/16097133

1.什么是时候需要使用动态SQL?
SQL文本在编译时是未知的。
例如,SELECT语句包含的标识符(如表名)在编译时是未知的,或者WHERE子句的条件数量在编译时是未知。
静态SQL不支持
例如,在PL/SQL中用静态SQL只能执行查询以及DML语句。如果想要执行DDL语句,只能使用动态SQL。
当让使用静态SQL,也有它的好处:
编译成功验证了静态SQL语句引用有效的数据库对象和访问这些对象的权限
编译成功创建了模式对象的依赖关系
2.EXECUTE IMMEDIATE语句
EXECUTE IMMEDIATE语句的意思是使用本地动态SQL处理大多数动态SQL语句。
如果动态SQL语句是自包含的(也就是说,它的绑定参数没有占位符,并且结果不可能返回错误),则EXECUTE IMMEDIATE语句不需要子句。
如果动态SQL语句包行占位符绑定参数,每个占位符在EXECUTE IMMEDIATE语句的子句中必须有一个相应的绑定参数,具体如下:
如果动态SQL语句是一个最多只能返回一行的SELECT语句,OUT绑定参数放置在INTO子句,IN绑定参数放置在USING子句。
如果动态SQL语句是一个可以返回多行的SELECT语句,OUT绑定参数放置在BULK COLLECT INTO子句,IN绑定参数放置在USING子句。
如果动态SQL语句是一个除了SELECT以外的其他DML语句,且没有RETURNING INTO子句,所有的绑定参数放置在USING子句中。
如果动态SQL还语句一个匿名PL/SQL块或CALL语句,把所有的绑定参数放置在USING子句中。
如果动态SQL语句调用一个子程序,请确保:
每个对应子程序参数占位符的绑定参数与子程序参数具有相同的参数模式和兼容的数据类型。
绑定参数不要有SQL不支持的数据类型(例如,布尔类型,关联数组,以及用户自定的记录类型)

USING子句不能包含NULL字面量。如果想要在USING子句中使用NULL值,可以使用位初始化的变量或者函数显示将NULL转换成一个有类型的值。

2.1动态SQL语句是一个最多只能返回一行的SELECT语句
使用动态SQL语句返回单列,查询SCOTT的薪水:
declare
v_sql_text varchar2(1000);
v_sal number;
v_ename emp.ename%type := 'SCOTT';
begin
v_sql_text := 'select e.sal from emp e where e.ename = :ename';
execute immediate v_sql_text
into v_sal
using v_ename;
dbms_output.put_line(v_ename || ':' || v_sal);
end;

使用动态SQL返回一条记录,查询SCOTT的基本信息:
declare
v_sql_text varchar2(1000);
v_ename emp.ename%type := 'SCOTT';
vrt_emp emp%rowtype;
begin
v_sql_text := 'select * from emp e where e.ename = :ename';
execute immediate v_sql_text
into vrt_emp
using v_ename;
dbms_output.put_line(v_ename || '的基本信息:');
dbms_output.put_line('工号:' || vrt_emp.empno);
dbms_output.put_line('工资:' || vrt_emp.sal);
dbms_output.put_line('入职日期:' || vrt_emp.hiredate);
end;

2.2动态SQL语句是一个可以返回多行的SELECT语句
2.2.1只有一个占位符
使用动态SQL语句返回多行记录,查询30部门的员工基本信息:
declare
v_sql_text varchar2(1000);
v_deptno emp.deptno%type := 30;
type nt_emp is table of emp%rowtype;
vnt_emp nt_emp;
begin
v_sql_text := 'select * from emp e where e.deptno = :deptno';
execute immediate v_sql_text bulk collect
into vnt_emp
using v_deptno;
for i in 1 .. vnt_emp.count loop
dbms_output.put_line(vnt_emp(i).ename || '的基本信息:');
dbms_output.put_line('工号:' || vnt_emp(i).empno);
dbms_output.put_line('工资:' || vnt_emp(i).sal);
dbms_output.put_line('入职日期:' || vnt_emp(i).hiredate);
dbms_output.put_line('');
end loop;
end

2.2.2多个占位符
查询20部门工资大于2000的员工基本信息:
declare
v_sql_text varchar2(1000);
v_deptno emp.deptno%type := 20;
v_sal number := 2000;
type nt_emp is table of emp%rowtype;
vnt_emp nt_emp;
begin
v_sql_text := 'select * from emp e where e.sal>:sal and e.deptno = :deptno';
execute immediate v_sql_text bulk collect
into vnt_emp
using v_sal, v_deptno; --注意绑定多个变量时,绑定变量只与占位符位置有关,与占位符名称无关,
for i in 1 .. vnt_emp.count loop
dbms_output.put_line(vnt_emp(i).ename || '的基本信息:');
dbms_output.put_line('工号:' || vnt_emp(i).empno);
dbms_output.put_line('工资:' || vnt_emp(i).sal);
dbms_output.put_line('入职日期:' || vnt_emp(i).hiredate);
dbms_output.put_line('');
end loop;

注意:对于SQL文本,占位符名称是没有意义的,绑定变量与占位符名称无关,只与占位符的配置有关。即使有多个相同名称占位符,也需要每个占位符对应一个绑定变量。对于PL/SQL块,占位符名称是有意义的,相同名称的占位符,只需要第一个占位符绑定变量。

2.3动态SQL语句是一个带有RETURNING子句的DML语句
KING的工资增长20%,返回增长后的工资:
eclare
v_sql_text varchar2(1000);
v_sal number;
v_ename emp.ename%type := 'KING';
begin
v_sql_text := 'update emp e set e.sal= e.sal*1.2 where e.ename = :ename returning e.sal into :sal';
execute immediate v_sql_text
using v_ename
returning into v_sal;
dbms_output.put_line(v_ename || ':' || v_sal);
end;

注意:只有当v_sql_text语句有returning into子句时,动态SQL语句才能使用returning into子句。

2.4给占位符传递NULL值
2.4.1通过未初始化变量传递NULL值
declare
v_sql_text varchar2(1000);
v_deptno emp.ename%type := 'ALLEN';
v_comm emp.comm%type;
begin
v_sql_text := 'update emp e set e.comm = :comm where e.ename =:ename';
execute immediate v_sql_text
using v_comm, v_deptno;
end;

2.4.2通过函数将NULL值显式的转换成一个有类型的值
declare
v_sql_text varchar2(1000);
v_deptno emp.ename%type := 'ALLEN';
begin
v_sql_text := 'update emp e set e.comm = :comm where e.ename =:ename';
execute immediate v_sql_text
using to_number(null), v_deptno;
end;

3.OPEN FOR语句
PL/SQL引入OPEN FOR语句实际上并不是为了支持本地动态SQL,而是为了支持游标变量。现在它以一种极其优雅的方式实现了多行的动态查询。
使用OPEN FOR语句来关联动态SQL语句的游标变量,在OPEN FOR语句的USING子句中,指定动态SQL语句每个占位符的绑定参数。
使用FETCH语句获取运行时结果集。
使用CLOSE语句关闭游标变量
使用OPEN FOR语句查询出10部门的员工的基本信息:
declare
type rc_emp is ref cursor;
vrc_emp rc_emp;
v_sql_text varchar2(1000);
v_deptno emp.deptno%type := 10;
vrt_emp emp%rowtype;
begin
v_sql_text := 'select * from emp e where e.deptno=:deptno';
open vrc_emp for v_sql_text
using v_deptno;
loop
exit when vrc_emp%notfound;
fetch vrc_emp
into vrt_emp;

dbms_output.put_line(vrt_emp.ename || '的基本信息:');
dbms_output.put_line('工号:' || vrt_emp.empno);
dbms_output.put_line('工资:' || vrt_emp.sal);
dbms_output.put_line('入职日期:' || vrt_emp.hiredate);
dbms_output.put_line('');

end loop;
close vrc_emp;
end;

4.重复的占位符名称
如果在动态SQL语句重复占位符名称,要知道占位符关联绑定参数的方式依赖于动态语句的类型。
如果执行的是一个动态SQL字符串,则必须为每一个占位符提供一个绑定参数,即使这些占位符是重复的。
如果执行的是一个动态PL/SQL块,则必须为每一个唯一占位符提供一个绑定参数,即重复的占位符只需要提供一个绑定参数。
4.1重复占位符的动态SQL字符串
declare
v_sql_text varchar2(1000);
v_sal emp.sal%type := 4000;
v_comm emp.comm%type;
v_ename emp.ename%type := 'SCOTT';
begin
v_sql_text := 'update emp e set e.sal=:sal , e.comm = :sal*0.1 where e.ename =:ename returning e.comm into :comm ';
execute immediate v_sql_text
using v_sal, v_sal, in v_ename
returning into v_comm;
dbms_output.put_line(v_ename || '分红:' || v_comm);
end;

4.2重复占位符的动态PL/SQL块
declare
v_sql_text varchar2(1000);
v_sal number;
v_ename emp.ename%type := 'KING';
begin
v_sql_text := ' begin select e.sal,e.ename into :sal,:ename from emp e where e.ename =:ename; end;';
execute immediate v_sql_text
using out v_sal, in out v_ename;
dbms_output.put_line(v_ename || ':' || v_sal);
end;

‘贰’ 如何生成ibatis 动态sql

IBATIS:最大的优点是可以有效的控制sql发送的数目,提高数据层的执行效率!好象阿里巴巴现在就用的是IBATIS;它需要程序员自己去写sql 语句,不想hibernate那样是完全面向对象的,自动化的,ibatis是半自动化的,通过表和对象的映射以及手工书写的sql语句,能够实现比 hibernate等更高的查询效率。

给个文章你参考下:

1.优点

简单:
易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

实用:
提供了数据映射功能,提供了对底层数据访问的封装(例如ado.net),提供了DAO框架,可以使我们更容易的开发和配置我们的DAL层。灵活:
通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。功能完整:
提供了连接管理,缓存支持,线程支持,(分布式)事物管理,通过配置作关系对象映射等数据访问层需要解决的问题。提供了DAO支持,并在DAO框架中封装了ADO.NET,NHibernate和DataMapper。增强系统的可维护性:
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
2.缺点

滞后性:
还没有明确对.NET2.0的支持。最新版本在2.0下编译可以,但有些单元测试不能通过。
不成熟,工程实践较少:
IbatisNet在实际项目中的使用较少。 只是理论上可行.
半ORM,工具支持较少:
需要我们自己写sql,并且.NET下还未发现可以自动生成业务层类和配置文件的工具,这点和NHibernate不一样,NHibernate会为我们的数据库直接产生sql,并有一些辅助工具。因此使用Ibatis比NHibernate要多做一些工作。
3.可行性

没有最好的框架,只有最适合的框架。存在的便是合理的,它存在就说明有它存在的道理。但它未必为我们存在。所以选择一个框架最主要的是看它对你有没有意义,意义有多大,是不是比其他框架带给你的好处要多。没有绝对的优点也没有绝对的缺点,重要的是看在什么情况下讨论。上面说了部分的Ibatis的优点和部分缺点。这些优点从理论上证明Ibatis对任何数据持久层都合适,但未必是最好的选择。下面对上面的优缺点分别从两方面讨论。简单:我们都喜欢简单,简单意味着学习成本低,使用中出错的可能性低。同时,简单的东西一般来说功能不够强大。反过来,复杂的东西学习成本高,用起来不方便,并且团队没有很强的技术实力,一般不要使用。实用:
解决了项目中需要解决的问题,这是任何实际工程中采用的框架和工具都应具有的性质,否则就不要拿到实际项目中来。灵活:灵活有两层意思,一种是简单易扩展,另一种是功能强大提供了很多选项。Ibatis属于前者,Hibernate属于后者。两者各有优缺点。功能完整: Ibatis的功能完整也是相对的,比我们自己开发的框架应该完整,但对比其他框架肯定也有一些解决不了的问题。增强系统的可维护性:利用Ibatis可以做到sql和代码分离,可以设计出一个清晰的数据访问层(DAL)。但项目架构是否科学合理,是否以维护,关键不在Ibatis,因为它只是一个数据层框架。但是我们也不得不清楚,要想发挥Ibatis的优势,我们需要做一些额外工作,比如最好设计DAO接口,需要将业务层实体和对实体的访问放在不同的工程中,同时需要维护xml配置文件。滞后性: Ibatis组现在还没有提到要支持.NET2.0,很多人在.NET2.0下使用Ibatis都出现了问题。所以如果要使用.NET2.0开发,IBatis不是一个好选择,还需要等待。不成熟:开源的东西很难说成熟,但一般比我们自己写的框架要成熟。由于我们可以拿到他的源代码,所以关键在于我们能否驾驭它。半ORM,工具支持少:这注定了Ibatis不能从本质上提升开发效率,我们需要自己写sql,写实体类,写配置文件。但这也是它优越的地方,它没有为我们做的他多,所以我们就有更多的施展空间。而且它非常适合那些并不能完全控制数据库的系统和需要利用数据库本身提供的高级特性的统计查询系统的开发。
使用Ibatis需要自己写sql,由于我们的sql不可能完全符合sql标准,比起NHibernate产生的sql来,可移植性差。不过由于我们更改数据库的可能性较小,对我们来说sql符合标准以便可以在迁移到不同服务器时代价最小并不是十分必要的。另一方面,NHibernate虽然可以屏蔽很多数据库间的不同,但是却很难利用某些数据库的高级特性,比如Oracle的分析统计函数。
NHibernate不适合数据库模式不规范,约束不完整,需要大量复杂查询的系统,同时NHibernate的学习成本较高,完全掌握 NHibernate也较困难,风险较大。 自己写框架未必比Ibatis的好,稳定,强大和可扩展。而且自己开发框架也需要较大的工作量。如果使用DotNet并且要选一个数据层框架,而系统中有相当一部分较复杂的sql,或数据库设计不合理,脏数据多,对性能和资源要求严格,Ibatis 是一个比较不错的选择。他的那些缺点并不是致命的,而且也是有一些解决方案的。尤其是,当选用了Ibatis的DataAccess作为DAO框架时,我们可以同时使用NHibernate,ADO.NET和DataMapper(IbatisNet的核心组件),那样将会使风险降到最低,并且整个系统的框架比较合理。
另外,利用Ibatis可以统一编码风格,节约开发成本,大家不会再把精力浪费到分页 连接池 主键生成等地方了,可以集中精力进行业务组件的编写。

综上:
很多时候我们要在是自己开发框架和选用第三方框架和选用什么样的框架问题上进行综合考虑。考虑的标准当然是项目的当前情况和我们希望达到目的的一个平衡。

Ibatis只是封装了数据访问层,替我们做了部分的对象关系映射。但我们的代价是必须要写xml配置文件,相对于Hibernate我们还要写很多 sql。Hibernate通过工具直接从数据库模式生成实体类和基本的配置文件,而且大部分情况下不需要我们写sql,会较大的提升开发效率。但这些也有很多的局限性,尤其是对环境的要求较高(数据库设计,对象设计,团队的协作等)。个人感觉Ibatis对项目比较有意义的地方在于它小巧灵活,可扩展,封装了数据访问层(事务,缓存,异常,日志),并提供了DAO框架支持。
利用Ibatis我们可以做到代码和sql的分离,只要sql能够解决的问题,Ibatis就能帮我们较容易的解决,同时也使我们的项目对某一框架的依赖性变小(因为Ibatis是非侵入性的)。这将极大的降低项目风险,减少解决复杂问题的时间,使项目的维护变得简单。
Ibatis对于应用的修改,调试,扩充和维护将会变得容易自然。修改时,我们主要修改的是代表模型的实体对象,xml配置文件中的sql,和/或配置文件的ResultMap(很多时候是不需要的)。同时,sql和代码分离,我们不用在代码的StringBuffer的append方法之间寻找需要修改的sql。配置文件中的sql便利了我们的调试和对sql的评审及以后的sql重用。
利用一些框架在前期一般会拖慢开发效率。因为我们需要付出学习成本,很多时候,使用框架需要写很多配置文件,在使用不熟时开发速度较慢;同时利用框架往往使系统代码量增大,比如Model1和Model2模型,开发效率应该还是Model1快,四层的架构肯定比两层的代码量大。但对于中后期开发和维护将会极大的提高效率。
利用一些较完全的开发框架和代码生成工具,在前期会较大的提高开发效率,但在后期常常会拖慢进度,并有可能成为以后维护的梦魇。比如torque生成实体类和其对应的sql,虽大幅提高了效率,但修改负担较大。
比较理想的开发方式是使用简单框架结合简单的代码生成工具。框架提供系统的基础服务,并规范开发。框架一方面提供了开发中某一方面的开发基础支持,比如数据访问层,事务,日志,公用类,异常等。另一方面,也为开发定义了模式,定义了系统的基本轮廓。同时,通过简单的代码生成工具生成部分低级的代码。比如通过工具从数据库模式生成实体类。这些类生成后我们可以自由修改。

Hibernate是十分强大,比较完善的ORM框架,不过这是它的优点也是它的缺点。 j2ee系统是否采用Hibernate3,是一个需要认真评估的问题。
要想Hibernate工作的好,数据库的设计必须好。同时对于复杂的数据操作同时需要使用sql,Hibernate3对于直接使用sql的支持比Hibernate2要自然,这一点是可以接受的。
Hibernate比较复杂,功能强大而灵活,要用好Hibernate确实不是很简单,当然Spring框架提供了对Hibernate的封装,使 Hibernate的使用变得简单了点。可以说Ibatis在任何系统里都适用,但未必是最好选择。不过Ibatis提供的思路是我们应该仔细考虑的。

‘叁’ 怎样在DAL层调用SQL写好的存储过程及BLL层的调用

BLL:public class TestBll { ITestDal dal = TestFactory.CreateDal(); public string GetData() { return dal.GetData(); } } IDAL: public interface ITestDal { public string GetData(); } DAL: public class TestDal : ITestDal { public override string GetData() { return "test"; } } Factory: public class TestFactory { public static ITestDal CreateDal() { return new TestDal(); } }

‘肆’ ASP.NET为什么我的sql语句一直不执行我的DAL层是这样写的,别的层没问题

我net学的不好,看不懂你写的。
strpassworpdate(string departmentname, string password1)这个是你定义的函数名和参数。

那么在写sql语句的时候就这样写:

string strsql = "update DanWei set password='"+password1+"' where departname='"+departmentname+"'";

我不知道你写的是不是对的,但是最好就是能输出你的sql语句,然后拿这个语句到数据库去执行,看看能不能成功。
能成功说明不是sql的问题,说不定就是你的数据库连接封装的函数写错了。

‘伍’ 什么是动态SQL语句

所谓动态sql,其实就是把sql语句使用字符串组装起来,然后使用 exec 关键字来运行的 语句。
如:
declare @sql = 'select 1 + 2'
exec @sql
这里的@sql就是动态sql

‘陆’ ASP.NET我的DAL层是这么写的,别的层都没问题,为什么sql语句不执行

这个无从下手,你到底是走语句呢还是存储过程呢,cf里怎么写的呢? ss是打酱油的吗?

‘柒’ Dal层的sql带参数的模糊查询语句

DataTable dt = SqlHelper.ExecuteDataTable("Select * from T_Warehouse where Material like @Material",new SqlParameter("@Material",string.Format("%{0}%", material));

这样写。

‘捌’ dal是数据连接层,写sql语句,添删改查,然后有返回值.BLL是业务逻辑层,model又是做什么用的,可以不用它吗

DAL是数据连接层,写sql语句,添删改查方法,然后有返回值。BLL是业务逻辑层,这里面不写sql语句,可以调用DAL层传过来的值做判断分析,并返回相应的值。最后在页面的隐藏代码中调用BLL的方法。

<connectionStrings>
<add name="ConnectionString" connectionString="Data Source=.;Initial Catalog=Database;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>

对你的DAL项目右键添加System.Configuration引用(必须步骤),
添加Model项目引用
然后在DB类(假设为UserDAL.cs)
using System.Configuration;//这个必须.
using Model那个项目
public class UserDAL
{
public const string ConnectionString = ConfigurationManager.ConnectionStrings [ "ConnectionString" ].ConnectionString;
public int Insert(UserInfo user)// Model
{

SqlConnection sqlcon=new SqlConnection ( ConnectionString );
.................
}
}

BLL
添加DB和Model项目引用
using 那个DB
public class UserBLL
{
public int Insert(UserInfo user)
{
int i = UserDAL.Insert(user);
}
}

‘玖’ ASP.NET 中DAL层的SQL语句问题.

第一种比较直观吧,不过不建议上边的写法,容易sql注入,还是建议用参数比较好