PL/SQL的一些问题

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关键字

原文地址:https://www.cnblogs.com/RicCC/p/1042147.html