您的位置:首页 > 数据库

PL/SQL的一些问题

2008-01-16 23:35 190 查看
1. Rownum

PL/SQL User's Guid and Reference中的描述:

ROWNUM returns a number indicating the order in which a row was selected from a table. The first row selected has a ROWNUM of 1, the second row has a ROWNUM of 2, and so on. If a SELECT statement includes an ORDER BY clause, ROWNUMs are assigned to the retrieved rows before the sort is done; use a subselect to get the first n sorted rows. The value of ROWNUM increases only when a row is retrieved, so the only meaningful uses of ROWNUM in a WHERE clause are:

... WHERE ROWNUM < constant;

... WHERE ROWNUM <= constant;

就是说Rownum是在读取记录时赋值,是在Order By操作之前,所以如果要排序,然后取一定位置的记录集,必须使用子查询。WHERE ROWNUM < constant1 AND ROWNUM>constant2;,如果constant2大于1,这个语句永远返回不了任何记录,必须使用子查询解决。

2. 关于排序的几个问题

DISTINCT

Select Distinct A From(

Select * From ATEST Order By B

)t2

上面语句子查询里面的Order By是没有作用的,因为外层查询的Distinct操作将重新排序。

HASH JOIN

跟Distinct一样,如果在子查询里面使用了Order By,外层查询有Hash Join出现,则子查询里面的Order By也无效,因为Hash算法会导致返回的结果集重新排序(Distinct操作也应当是使用Hash算法实现的)。Hash算法结果的排序应当依赖于从probe input读取记录的顺序,但算法本身的实现方式也可能造成影响,另外Hash的两个输入可能经过优化器的动态选择,所以结果的排序具有不确定性。

例如下面的写法:

Select ...

From(

Select t1.*,Rownum As RowIndex

From (Select * From A Where ... Order By ...)t1

Where t1.RowIndex>:startIndex And t1.RowIndex<=:endIndex

)t2

Left Join B On ...

出发点是好的:先从A中按照条件和排序规则取出指定页数的记录集,然后再和B关联,降低关联算法的数据运算量。大部分情况下结果会是正确的,因为Oracle将优先采用Nested Loop方式进行关联,这种算法不会影响排序(Merge也不会影响排序),但如果子查询返回的记录集太大、B表上没有用于关联的索引、或索引没有维护等,就可能采用Hash算法,这时返回结果的排序就不一定正确了。

上面的问题在需要分页的语句中容易发生的。SQL Server对子查询中使用Order By有限制,所以情况好一点,Oracle的PL/SQL没有这方面限制,所以开发的时候很容易被忽视,而发布之后被最终用户发现。

3. 关键字冲突问题

相比Oracle,SQL Server对关键字冲突的处理要宽松很多,Oracle则要求严格

例如Create Table A( Id Number(8), "Level" Number(2));可以创建表,但select id,"Level" from a则会报错"Level"标识符无效

ORM处理方法参考:

首先,表名、字段名不能与Oracle关键字冲突,ORM需要处理的,是避免对象名、属性名(考虑对象、属性与表名、字段名不同的情况)、参数名的冲突问题

NHibernate对查询中的表、字段、参数都重新命名,例如生成的SQL类似如下

select t_0.OrgCode as t_0_0,t_0.ItemNo as t_0_1

,t_1.ItemName as t_1_0,t_1.ItemUOM as t_1_1

from dbo.TblOrgItem t_0

inner join dbo.TblItem t_1 on t_0.ItemID=t_1.oid

where t_0.OrgCode=@p_0 and t_1.ItemName like @p_1

在NHibernate内部新的名称和原对象的对应关系是清晰的, t_1_0这个字段会设置到dob.TblItem对应对象的相应属性上

4. 语法细节差异

4.1 select a.* from TableA as a,这个语句SQL Server正常,而Oracle会报错,因为Oracle指定Table的别名不能使用AS关键字
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: