SQL Server、Access、Oracle都是数据库平台,都支持SQL,但有差异。通常是语义相近而形式不同,但也有形似而含义不同的。有的差异是细节的,有的差异还不小。如果不注意这些差异就可能会被困扰,于是把最近遇到的有关差异整理了一下,将来还会扩充。

一、多表连接更新的差异

Access形式最简洁,SQL Server略麻烦(加个from跟多个表名,保证update和set之间只有一个表名),Oracle有点怪,用嵌套实现。

SQL Server:

update qsdc

set sjyt=地类代号,mc2=地类名称

from 国有集体,qsdc

where 国有集体.区号=qsdc.qh

and 国有集体.街道号=qsdc.jdh

and 国有集体.街坊号=qsdc.jfh

and 国有集体.宗地号=qsdc.zdh

and sjyt<>地类代号

Access:

update ma_ZD_QLR,MA_ZD
    set ma_ZD_QLR.BSM=MA_ZD.BSM,
        ma_ZD_QLR.pcode=MA_ZD.pcode
  where MA_ZD.djh=ma_ZD_QLR.djh
and ma_ZD_QLR.BSM=0
Oracle:
Create Table TabA(
            ID int,
            name varchar2(20)
);
Create Table TabB(
            ID int,
            name varchar2(20)
);
insert into TabA values(1,'ABC');
insert into TabA values(2,'DEF');
insert into TabA values(3,'GHI');
 
insert into TabB values(1,'');
insert into TabB values(2,'');
 
update TabB 
set TabB.NAME=(selectTabA.NAME fromTabA where TabB.ID=TabA.ID) 
where TabB.ID IN (select ID from TabA);

说明:

如果直接执行select TabA.NAME fromTabA where TabB.ID=TabA.ID是不行的,而要用selectTabA.NAME fromTabA,TabB where TabB.ID=TabA.ID才能被正确执行,但是在这里被嵌套的这里TabB反倒是不能写的。通常被嵌套的select语句是能够独立执行的,这就是称之为“怪”的原因。

二、外连接的差异

以左外连接为例,SQL Server用LEFT OUTER JOIN,Access和Oracle用LEFT JOIN。

SQL Server:
select *  from ShengChan as S
                 LEFT OUTER JOIN
                   ZhiLiang as Z
                on (Z.合同号=S.合同号),
       XiaDaRen as X,
       SheJi as J
where X.合同号=S.合同号and j.合同号=S.合同号;
这是三个表等值连接再对ZhiLiang表作左外连接。
Access:
Select * from (ma_zd  LEFT JOIN ma_fw ON ma_zd.djh=ma_fw.lszd )
Oracle:
select * from PersonMain主表
left join PersonJingPin精品库表
            on 主表.个人标识=精品库表.个人标识
left join  PersonCongYe职业表
            on 主表.个人标识=职业表.个人标识
left join PersonCongYi从医表
            on 主表.个人标识=从医表.个人标识
where 精品库代码 like '%,13,%';
这是一个主表对三个从表作左外连接。

三、NULL值处理差异

外联接就会有NULL,在数值计算时,常常要用0、’空’、’无’等代替。

SQL Server:

select isnull(zdmj,0) from qsdc;

Access:

select NZ(ma_fw.SHAPE_Area,0) from ma_fw;

Oracle:

selectnvl(name,'无') from TabA;

四、嵌套查询差异

SQL Server与Access基本一致,在查询结果前后加一对圆括号,并以As别名紧跟;Oracle不要As,把查询结果括起来后直接跟别名。经过如此别名命名之后,被嵌套的中间查询结果就可以当作关系表一样来引用,这个功能极大地扩充了单条SQL语句的威力,尤其对没有提供类似T-SQL、PL/SQL等过程化语言扩展的Access这样的平台,显得尤为重要。

SQL Server:

select * from 
(
            select * from国有集体 ,qsdc
            where国有集体.区号=qsdc.qh
            and国有集体.街道号=qsdc.jdh
            and国有集体.街坊号=qsdc.jfh 
            and国有集体.宗地号=qsdc.zdh
) as aa
,tdsq 
where aa.qh=tdsq.qh 
and aa.jdh=tdsq.jdh 
and aa.jfh=tdsq.jfh  
and aa.zdh=tdsq.zdh  
Access:
select left(d.LSZD,9) as行政区划代码,sum(Area_jzmj) as建筑面积 from 
(
    select LSZD,sum(SHAPE_Area*FWCS) as Area_jzmj from ma_fw
    group by LSZD
) as d
group by left(d.LSZD,9)
Oracle:
写法相近,但不要as关键字:
select ID_A from
(
            select A.ID ID_A, A.NAME,B.ID ID_B
            from taba A, tabb B
            where A.ID=B.ID
) T;

五、Select Into差异

SQL Server和Access中都用于将查询结果的记录集输出到新表中(新表不需要事先存在),Oracle的Select Into是PL/SQL中使用的,有点像SQL ServerT-SQL中的Fetch Into。

SQL Server:

select * into newTAB

from 国有集体

Access:

select B.OBJECTID, B.xh-A.zd_xh+1 as FWBH_
             into myFWBH_ from
 ( 
             select min(xh) as zd_xh,LSZD as zd from myFWBH
             group by LSZD
 ) as A, 
 myFWBH as B 
 where A.zd=B.LSZD 
 order by B.xh

(这实际上还是个自连接。)

Oracle:

写法上差异似乎不那么大,但概念不一样了,是PL/SQL中用于将单行记录的字段值赋给PL/SQL变量,Into后面不是表名而是PL/SQL变量,比如:

Select SUM(SALARY),SUM(SALARY*0.1)
Into TOTAL_SALARY,TATAL_COMMISSION
From EMPLOYEE
Where DEPT=10;
而如果要实现类似SQL Server、Access中Select Into语句的效果,可以使用Oracle的Create Table As语句,如下:
create table TabE as 
select * from TabA 
where id<3;