MS Jet中奇怪的问题?

Kanas.net 1.3在紧张的测试中。为了保证数据库支持的中立性,采用SQL标准实现最差的MS Jet(MS Access 2000格式载体,使用ADO.NET的OleDb引擎)。以往这种数据库配置用得比较少,对其特异性严重掌握不够,导致排错效率不高。
其中有一个TestCase出现的bug狂找了一个小时才发现,真是哭笑不得。

大家看看以下两个SQL语句,相同的指令,不同的结果:
命令文本:update debtors set debit=@P3,searches=@P4 where id=@P2
参数表:
  @P2=16
  @P3=3650
  @P4=520
(所影响的行数为 0 行)
命令文本:update debtors set debit=@P1,searches=@P2 where id=16
参数表:
  @P1=3650
  @P2=520
(所影响的行数为 1 行)
而在Sql Server中则不会出现类似这样的问题。

0
0
(请您对文章做出评价)
« 上一篇:一年来我最好的创意
» 下一篇:Lazy Load vs Immediately Load?
posted @ 2005-08-10 02:12 双鱼座 阅读(1206) 评论(7)  编辑 收藏

  回复  引用  查看    
#1楼2005-08-10 09:05 | Teddy's Knowledge Base      
这个是ado oledb驱动的老问题了,传入参数必须按sql中参数出现的顺序,sql不会有这样的问题。不过在ado.net下面,除了sqlserver就都难以避免了,不过好在,一般使用框架时如果sql是由程序动态构造的一般不会出现参数顺序不一致,我原来被这个问题折腾也是在测试用例中:)当时查了一下才发现真的是一个很早就广为流传的问题了,并且不是bug,而是因为oledb支持通用的db,但有很多db本身识别参数的时候不按名称只按顺序的,所以也是没办法的。

其实还有另一个问题:
在sqlserver中:select * from table where param1 = @p1 and param2 = @p2 and param3 = @p1
@p1=1
@p2=2
是完全没问题的

但是如果对oledb驱动就不行了,必须以三个参数对待,同样是因为oledb只按参数索引顺序,不按名称来为参数赋值。

  回复  引用  查看    
#2楼2005-08-10 09:42 | Teddy's Knowledge Base      
谈到sql语法差异,我再说两点access和sqlserver中的不同,希望对你所有帮助:

一个是access不支持select top 0 from table这样的语句,注意top后面的数字不能是0,如果大于0没问题,但是sqlserver下是没问题的。发现这个问题是在我的一个基于代码生成的框架中自动通过形如select columns from table这样的简单语句为每个实体类生成形如select top {0} ... where not in (select top {1}...)...这样的通用分页查询语句,当区第一页数据的时候,not in 后面的top {1}中,{1}将会是0,这时access就会报错,所以最后对取第一页的情况我只能区别对待。

再一个是像select * from (select * from table)这样的语法,在access下没问题,在sqlserver下则必须在后面为动态表指定一个别名语法才是正确的:select * from (select * from table) aliasname,aliasname可以是任意的单词。之所以使用这样的语句同样是为了通过形如select columns from table这样的简单语句构造分页语句时用来返回所有的记录总数:select count(ID) from (select columns from table),当然这样是偷懒,性能上应该会有部分影响的,count的时候尽可能还是建议直接用select count(ID) from table这样的句法。

  回复  引用  查看    
#3楼[楼主]2005-08-10 12:54 | 双鱼座      
@Teddy's Knowledge Base:
非常感谢你的提示,你的提示对我非常重要。我没有使用类似Hibernate中的Dialect体系,我觉得在.net下的应用背景与java下相差很大。在IDbProvider中我只定义了一个参数名修饰。
如果是参数顺序的问题,我可以在build sql的时候保证定义次序与参数次序完全一致。事实上,在sql builder中,参数名称集合是一张表,参数值中另外一张表,而真正生成IDataParameter是运行时才做的,所以调整顺序并不困难。

  回复  引用  查看    
#4楼2005-08-10 14:43 | 蛙蛙池塘      
没错,access确实支持参数化查询,但是你设置的参数名不会有用的,是按顺序赋值的,上次我都折腾了好一阵子.
  回复  引用    
#5楼2005-08-10 18:25 | fancyf[未注册用户]
Access不支持命名的参数

用标准的方式就不会发生误解了:
update debtors set debit=?,searches=? where id=?
然后按顺序添加参数

  回复  引用  查看    
#6楼[楼主]2005-08-10 20:03 | 双鱼座      
非常感谢蛙蛙池塘和fancyf共享你们的经验...
  回复  引用  查看    
#7楼2005-08-16 18:46 | IT      
ACCESS不支持多个语句一起执行

delete * from table;
insert into table(field)values(value);
而在SQL SERVER明显能执行